blob: 7b18cf214ea303c38c87354d9ea4bb0903c1462f [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
1106 return ret;
1107}
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 Follath867a3ab2019-10-11 14:21:53 +01001150 * If Y->p[i - 1] < X->p[i - 1] and both X and Y are negative, then
1151 * X < Y.
1152 *
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 Follath1f21c1d2019-10-28 12:31:34 +00001156 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] ) & X_is_negative;
Janos Follath867a3ab2019-10-11 14:21:53 +01001157 *ret |= cond & ( 1 - done );
Janos Follath4f6cf382019-10-11 10:43:40 +01001158 done |= cond & ( 1 - done );
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001159
1160 /*
Janos Follath867a3ab2019-10-11 14:21:53 +01001161 * If X->p[i - 1] < Y->p[i - 1] and both X and Y are positive, then
1162 * X < Y.
1163 *
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 Follath1f21c1d2019-10-28 12:31:34 +00001167 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] )
1168 & ( 1 - X_is_negative );
Janos Follath867a3ab2019-10-11 14:21:53 +01001169 *ret |= cond & ( 1 - done );
Janos Follath4f6cf382019-10-11 10:43:40 +01001170 done |= cond & ( 1 - done );
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001171 }
1172
1173 return( 0 );
1174}
1175
Paul Bakker5121ce52009-01-03 21:22:43 +00001176/*
1177 * Compare signed values
1178 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001179int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001180{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001181 mbedtls_mpi Y;
1182 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001183 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001184
1185 *p = ( z < 0 ) ? -z : z;
1186 Y.s = ( z < 0 ) ? -1 : 1;
1187 Y.n = 1;
1188 Y.p = p;
1189
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001190 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001191}
1192
1193/*
1194 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1195 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001196int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001197{
Paul Bakker23986e52011-04-24 08:57:21 +00001198 int ret;
1199 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001200 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001201 MPI_VALIDATE_RET( X != NULL );
1202 MPI_VALIDATE_RET( A != NULL );
1203 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001204
1205 if( X == B )
1206 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001207 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001208 }
1209
1210 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001211 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001212
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001213 /*
1214 * X should always be positive as a result of unsigned additions.
1215 */
1216 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001217
Paul Bakker23986e52011-04-24 08:57:21 +00001218 for( j = B->n; j > 0; j-- )
1219 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001220 break;
1221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001222 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001223
1224 o = B->p; p = X->p; c = 0;
1225
Janos Follath6c922682015-10-30 17:43:11 +01001226 /*
1227 * tmp is used because it might happen that p == o
1228 */
Paul Bakker23986e52011-04-24 08:57:21 +00001229 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001230 {
Janos Follath6c922682015-10-30 17:43:11 +01001231 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001232 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001233 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001234 }
1235
1236 while( c != 0 )
1237 {
1238 if( i >= X->n )
1239 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001240 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001241 p = X->p + i;
1242 }
1243
Paul Bakker2d319fd2012-09-16 21:34:26 +00001244 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001245 }
1246
1247cleanup:
1248
1249 return( ret );
1250}
1251
1252/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001253 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001254 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001255static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001256{
Paul Bakker23986e52011-04-24 08:57:21 +00001257 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001258 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001259
1260 for( i = c = 0; i < n; i++, s++, d++ )
1261 {
1262 z = ( *d < c ); *d -= c;
1263 c = ( *d < *s ) + z; *d -= *s;
1264 }
1265
1266 while( c != 0 )
1267 {
1268 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001269 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001270 }
1271}
1272
1273/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001274 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001275 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001276int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001277{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001278 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001279 int ret;
1280 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001281 MPI_VALIDATE_RET( X != NULL );
1282 MPI_VALIDATE_RET( A != NULL );
1283 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001284
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001285 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1286 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001287
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001288 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001289
1290 if( X == B )
1291 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001292 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001293 B = &TB;
1294 }
1295
1296 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001297 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001298
Paul Bakker1ef7a532009-06-20 10:50:55 +00001299 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001300 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001301 */
1302 X->s = 1;
1303
Paul Bakker5121ce52009-01-03 21:22:43 +00001304 ret = 0;
1305
Paul Bakker23986e52011-04-24 08:57:21 +00001306 for( n = B->n; n > 0; n-- )
1307 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001308 break;
1309
Paul Bakker23986e52011-04-24 08:57:21 +00001310 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001311
1312cleanup:
1313
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001314 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001315
1316 return( ret );
1317}
1318
1319/*
1320 * Signed addition: X = A + B
1321 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001322int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001323{
Hanno Becker73d7d792018-12-11 10:35:51 +00001324 int ret, s;
1325 MPI_VALIDATE_RET( X != NULL );
1326 MPI_VALIDATE_RET( A != NULL );
1327 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001328
Hanno Becker73d7d792018-12-11 10:35:51 +00001329 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001330 if( A->s * B->s < 0 )
1331 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001333 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001334 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001335 X->s = s;
1336 }
1337 else
1338 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001339 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001340 X->s = -s;
1341 }
1342 }
1343 else
1344 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001345 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001346 X->s = s;
1347 }
1348
1349cleanup:
1350
1351 return( ret );
1352}
1353
1354/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001355 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001356 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001357int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001358{
Hanno Becker73d7d792018-12-11 10:35:51 +00001359 int ret, s;
1360 MPI_VALIDATE_RET( X != NULL );
1361 MPI_VALIDATE_RET( A != NULL );
1362 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001363
Hanno Becker73d7d792018-12-11 10:35:51 +00001364 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001365 if( A->s * B->s > 0 )
1366 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001367 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001368 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001369 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001370 X->s = s;
1371 }
1372 else
1373 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001374 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001375 X->s = -s;
1376 }
1377 }
1378 else
1379 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001380 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001381 X->s = s;
1382 }
1383
1384cleanup:
1385
1386 return( ret );
1387}
1388
1389/*
1390 * Signed addition: X = A + b
1391 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001393{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001394 mbedtls_mpi _B;
1395 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001396 MPI_VALIDATE_RET( X != NULL );
1397 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001398
1399 p[0] = ( b < 0 ) ? -b : b;
1400 _B.s = ( b < 0 ) ? -1 : 1;
1401 _B.n = 1;
1402 _B.p = p;
1403
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001404 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001405}
1406
1407/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001408 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001409 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001410int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001411{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001412 mbedtls_mpi _B;
1413 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001414 MPI_VALIDATE_RET( X != NULL );
1415 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001416
1417 p[0] = ( b < 0 ) ? -b : b;
1418 _B.s = ( b < 0 ) ? -1 : 1;
1419 _B.n = 1;
1420 _B.p = p;
1421
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001422 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001423}
1424
1425/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001426 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001427 */
1428static
1429#if defined(__APPLE__) && defined(__arm__)
1430/*
1431 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1432 * appears to need this to prevent bad ARM code generation at -O3.
1433 */
1434__attribute__ ((noinline))
1435#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001436void 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 +00001437{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001438 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001439
1440#if defined(MULADDC_HUIT)
1441 for( ; i >= 8; i -= 8 )
1442 {
1443 MULADDC_INIT
1444 MULADDC_HUIT
1445 MULADDC_STOP
1446 }
1447
1448 for( ; i > 0; i-- )
1449 {
1450 MULADDC_INIT
1451 MULADDC_CORE
1452 MULADDC_STOP
1453 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001454#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001455 for( ; i >= 16; i -= 16 )
1456 {
1457 MULADDC_INIT
1458 MULADDC_CORE MULADDC_CORE
1459 MULADDC_CORE MULADDC_CORE
1460 MULADDC_CORE MULADDC_CORE
1461 MULADDC_CORE MULADDC_CORE
1462
1463 MULADDC_CORE MULADDC_CORE
1464 MULADDC_CORE MULADDC_CORE
1465 MULADDC_CORE MULADDC_CORE
1466 MULADDC_CORE MULADDC_CORE
1467 MULADDC_STOP
1468 }
1469
1470 for( ; i >= 8; i -= 8 )
1471 {
1472 MULADDC_INIT
1473 MULADDC_CORE MULADDC_CORE
1474 MULADDC_CORE MULADDC_CORE
1475
1476 MULADDC_CORE MULADDC_CORE
1477 MULADDC_CORE MULADDC_CORE
1478 MULADDC_STOP
1479 }
1480
1481 for( ; i > 0; i-- )
1482 {
1483 MULADDC_INIT
1484 MULADDC_CORE
1485 MULADDC_STOP
1486 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001487#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001488
1489 t++;
1490
1491 do {
1492 *d += c; c = ( *d < c ); d++;
1493 }
1494 while( c != 0 );
1495}
1496
1497/*
1498 * Baseline multiplication: X = A * B (HAC 14.12)
1499 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001500int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001501{
Paul Bakker23986e52011-04-24 08:57:21 +00001502 int ret;
1503 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001504 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001505 MPI_VALIDATE_RET( X != NULL );
1506 MPI_VALIDATE_RET( A != NULL );
1507 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001509 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1512 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001513
Paul Bakker23986e52011-04-24 08:57:21 +00001514 for( i = A->n; i > 0; i-- )
1515 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001516 break;
1517
Paul Bakker23986e52011-04-24 08:57:21 +00001518 for( j = B->n; j > 0; j-- )
1519 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001520 break;
1521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001522 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1523 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001524
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001525 for( ; j > 0; j-- )
1526 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001527
1528 X->s = A->s * B->s;
1529
1530cleanup:
1531
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001532 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001533
1534 return( ret );
1535}
1536
1537/*
1538 * Baseline multiplication: X = A * b
1539 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001540int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001541{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001542 mbedtls_mpi _B;
1543 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001544 MPI_VALIDATE_RET( X != NULL );
1545 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001546
1547 _B.s = 1;
1548 _B.n = 1;
1549 _B.p = p;
1550 p[0] = b;
1551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001552 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001553}
1554
1555/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001556 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1557 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001558 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001559static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1560 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001561{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001562#if defined(MBEDTLS_HAVE_UDBL)
1563 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001564#else
Simon Butcher9803d072016-01-03 00:24:34 +00001565 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1566 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001567 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1568 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001569 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001570#endif
1571
Simon Butcher15b15d12015-11-26 19:35:03 +00001572 /*
1573 * Check for overflow
1574 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001575 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001576 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001577 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001578
Simon Butcherf5ba0452015-12-27 23:01:55 +00001579 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001580 }
1581
1582#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001583 dividend = (mbedtls_t_udbl) u1 << biL;
1584 dividend |= (mbedtls_t_udbl) u0;
1585 quotient = dividend / d;
1586 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1587 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1588
1589 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001590 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001591
1592 return (mbedtls_mpi_uint) quotient;
1593#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001594
1595 /*
1596 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1597 * Vol. 2 - Seminumerical Algorithms, Knuth
1598 */
1599
1600 /*
1601 * Normalize the divisor, d, and dividend, u0, u1
1602 */
1603 s = mbedtls_clz( d );
1604 d = d << s;
1605
1606 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001607 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001608 u0 = u0 << s;
1609
1610 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001611 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001612
1613 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001614 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001615
1616 /*
1617 * Find the first quotient and remainder
1618 */
1619 q1 = u1 / d1;
1620 r0 = u1 - d1 * q1;
1621
1622 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1623 {
1624 q1 -= 1;
1625 r0 += d1;
1626
1627 if ( r0 >= radix ) break;
1628 }
1629
Simon Butcherf5ba0452015-12-27 23:01:55 +00001630 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001631 q0 = rAX / d1;
1632 r0 = rAX - q0 * d1;
1633
1634 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1635 {
1636 q0 -= 1;
1637 r0 += d1;
1638
1639 if ( r0 >= radix ) break;
1640 }
1641
1642 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001643 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001644
1645 quotient = q1 * radix + q0;
1646
1647 return quotient;
1648#endif
1649}
1650
1651/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001652 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001653 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001654int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1655 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001656{
Paul Bakker23986e52011-04-24 08:57:21 +00001657 int ret;
1658 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001659 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001660 MPI_VALIDATE_RET( A != NULL );
1661 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001662
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001663 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1664 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001665
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001666 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1667 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001669 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001670 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1672 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001673 return( 0 );
1674 }
1675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001676 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1677 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001678 X.s = Y.s = 1;
1679
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001680 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1681 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1682 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1683 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001684
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001685 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001686 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001687 {
1688 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001689 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1690 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001691 }
1692 else k = 0;
1693
1694 n = X.n - 1;
1695 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001696 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001697
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001698 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001699 {
1700 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001701 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001702 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001703 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001704
1705 for( i = n; i > t ; i-- )
1706 {
1707 if( X.p[i] >= Y.p[t] )
1708 Z.p[i - t - 1] = ~0;
1709 else
1710 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001711 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1712 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001713 }
1714
1715 Z.p[i - t - 1]++;
1716 do
1717 {
1718 Z.p[i - t - 1]--;
1719
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001720 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001721 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001722 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001723 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001724
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001725 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001726 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1727 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001728 T2.p[2] = X.p[i];
1729 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001730 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001731
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001732 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1733 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1734 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001735
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001736 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001737 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001738 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1739 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1740 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001741 Z.p[i - t - 1]--;
1742 }
1743 }
1744
1745 if( Q != NULL )
1746 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001747 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001748 Q->s = A->s * B->s;
1749 }
1750
1751 if( R != NULL )
1752 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001753 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001754 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001756
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001757 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001758 R->s = 1;
1759 }
1760
1761cleanup:
1762
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001763 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1764 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001765
1766 return( ret );
1767}
1768
1769/*
1770 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001771 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001772int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1773 const mbedtls_mpi *A,
1774 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001775{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001776 mbedtls_mpi _B;
1777 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001778 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001779
1780 p[0] = ( b < 0 ) ? -b : b;
1781 _B.s = ( b < 0 ) ? -1 : 1;
1782 _B.n = 1;
1783 _B.p = p;
1784
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001785 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001786}
1787
1788/*
1789 * Modulo: R = A mod B
1790 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001791int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001792{
1793 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001794 MPI_VALIDATE_RET( R != NULL );
1795 MPI_VALIDATE_RET( A != NULL );
1796 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001797
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001798 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1799 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001800
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001801 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001802
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001803 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1804 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001805
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001806 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1807 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001808
1809cleanup:
1810
1811 return( ret );
1812}
1813
1814/*
1815 * Modulo: r = A mod b
1816 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001817int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001818{
Paul Bakker23986e52011-04-24 08:57:21 +00001819 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001820 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001821 MPI_VALIDATE_RET( r != NULL );
1822 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001823
1824 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001825 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001826
1827 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001828 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001829
1830 /*
1831 * handle trivial cases
1832 */
1833 if( b == 1 )
1834 {
1835 *r = 0;
1836 return( 0 );
1837 }
1838
1839 if( b == 2 )
1840 {
1841 *r = A->p[0] & 1;
1842 return( 0 );
1843 }
1844
1845 /*
1846 * general case
1847 */
Paul Bakker23986e52011-04-24 08:57:21 +00001848 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001849 {
Paul Bakker23986e52011-04-24 08:57:21 +00001850 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001851 y = ( y << biH ) | ( x >> biH );
1852 z = y / b;
1853 y -= z * b;
1854
1855 x <<= biH;
1856 y = ( y << biH ) | ( x >> biH );
1857 z = y / b;
1858 y -= z * b;
1859 }
1860
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001861 /*
1862 * If A is negative, then the current y represents a negative value.
1863 * Flipping it to the positive side.
1864 */
1865 if( A->s < 0 && y != 0 )
1866 y = b - y;
1867
Paul Bakker5121ce52009-01-03 21:22:43 +00001868 *r = y;
1869
1870 return( 0 );
1871}
1872
1873/*
1874 * Fast Montgomery initialization (thanks to Tom St Denis)
1875 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001876static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001877{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001878 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001879 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001880
1881 x = m0;
1882 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001883
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001884 for( i = biL; i >= 8; i /= 2 )
1885 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001886
1887 *mm = ~x + 1;
1888}
1889
1890/*
1891 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1892 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001893static 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 +02001894 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001895{
Paul Bakker23986e52011-04-24 08:57:21 +00001896 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001897 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001898
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001899 if( T->n < N->n + 1 || T->p == NULL )
1900 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1901
Paul Bakker5121ce52009-01-03 21:22:43 +00001902 memset( T->p, 0, T->n * ciL );
1903
1904 d = T->p;
1905 n = N->n;
1906 m = ( B->n < n ) ? B->n : n;
1907
1908 for( i = 0; i < n; i++ )
1909 {
1910 /*
1911 * T = (T + u0*B + u1*N) / 2^biL
1912 */
1913 u0 = A->p[i];
1914 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1915
1916 mpi_mul_hlp( m, B->p, d, u0 );
1917 mpi_mul_hlp( n, N->p, d, u1 );
1918
1919 *d++ = u0; d[n + 1] = 0;
1920 }
1921
Paul Bakker66d5d072014-06-17 16:39:18 +02001922 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001923
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001924 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001925 mpi_sub_hlp( n, N->p, A->p );
1926 else
1927 /* prevent timing attacks */
1928 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001929
1930 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001931}
1932
1933/*
1934 * Montgomery reduction: A = A * R^-1 mod N
1935 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001936static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1937 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001938{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001939 mbedtls_mpi_uint z = 1;
1940 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001941
Paul Bakker8ddb6452013-02-27 14:56:33 +01001942 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001943 U.p = &z;
1944
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001945 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001946}
1947
1948/*
1949 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1950 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001951int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1952 const mbedtls_mpi *E, const mbedtls_mpi *N,
1953 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001954{
Paul Bakker23986e52011-04-24 08:57:21 +00001955 int ret;
1956 size_t wbits, wsize, one = 1;
1957 size_t i, j, nblimbs;
1958 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959 mbedtls_mpi_uint ei, mm, state;
1960 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001961 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001962
Hanno Becker73d7d792018-12-11 10:35:51 +00001963 MPI_VALIDATE_RET( X != NULL );
1964 MPI_VALIDATE_RET( A != NULL );
1965 MPI_VALIDATE_RET( E != NULL );
1966 MPI_VALIDATE_RET( N != NULL );
1967
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001968 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001969 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001970
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001971 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1972 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001973
1974 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001975 * Init temps and window size
1976 */
1977 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001978 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1979 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001980 memset( W, 0, sizeof( W ) );
1981
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001982 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001983
1984 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1985 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1986
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001987#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1989 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001990#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001991
Paul Bakker5121ce52009-01-03 21:22:43 +00001992 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001993 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1994 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1995 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001996
1997 /*
Paul Bakker50546922012-05-19 08:40:49 +00001998 * Compensate for negative A (and correct at the end)
1999 */
2000 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002001 if( neg )
2002 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002003 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002004 Apos.s = 1;
2005 A = &Apos;
2006 }
2007
2008 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002009 * If 1st call, pre-compute R^2 mod N
2010 */
2011 if( _RR == NULL || _RR->p == NULL )
2012 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002013 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2014 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2015 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002016
2017 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002018 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002019 }
2020 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002021 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
2023 /*
2024 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2025 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002026 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2027 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002028 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002030
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002031 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002032
2033 /*
2034 * X = R^2 * R^-1 mod N = R mod N
2035 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002036 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002037 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002038
2039 if( wsize > 1 )
2040 {
2041 /*
2042 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2043 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002044 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002045
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2047 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002048
2049 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002050 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002051
Paul Bakker5121ce52009-01-03 21:22:43 +00002052 /*
2053 * W[i] = W[i - 1] * W[1]
2054 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002055 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002056 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002057 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2058 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002059
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002060 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002061 }
2062 }
2063
2064 nblimbs = E->n;
2065 bufsize = 0;
2066 nbits = 0;
2067 wbits = 0;
2068 state = 0;
2069
2070 while( 1 )
2071 {
2072 if( bufsize == 0 )
2073 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002074 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002075 break;
2076
Paul Bakker0d7702c2013-10-29 16:18:35 +01002077 nblimbs--;
2078
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002079 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002080 }
2081
2082 bufsize--;
2083
2084 ei = (E->p[nblimbs] >> bufsize) & 1;
2085
2086 /*
2087 * skip leading 0s
2088 */
2089 if( ei == 0 && state == 0 )
2090 continue;
2091
2092 if( ei == 0 && state == 1 )
2093 {
2094 /*
2095 * out of window, square X
2096 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002097 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002098 continue;
2099 }
2100
2101 /*
2102 * add ei to current window
2103 */
2104 state = 2;
2105
2106 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002107 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002108
2109 if( nbits == wsize )
2110 {
2111 /*
2112 * X = X^wsize R^-1 mod N
2113 */
2114 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002115 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002116
2117 /*
2118 * X = X * W[wbits] R^-1 mod N
2119 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002120 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002121
2122 state--;
2123 nbits = 0;
2124 wbits = 0;
2125 }
2126 }
2127
2128 /*
2129 * process the remaining bits
2130 */
2131 for( i = 0; i < nbits; i++ )
2132 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002133 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002134
2135 wbits <<= 1;
2136
Paul Bakker66d5d072014-06-17 16:39:18 +02002137 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002138 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002139 }
2140
2141 /*
2142 * X = A^E * R * R^-1 mod N = A^E mod N
2143 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002144 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002145
Hanno Beckera4af1c42017-04-18 09:07:45 +01002146 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002147 {
2148 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002149 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002150 }
2151
Paul Bakker5121ce52009-01-03 21:22:43 +00002152cleanup:
2153
Paul Bakker66d5d072014-06-17 16:39:18 +02002154 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002155 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002156
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002157 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002158
Paul Bakker75a28602014-03-31 12:08:17 +02002159 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002161
2162 return( ret );
2163}
2164
Paul Bakker5121ce52009-01-03 21:22:43 +00002165/*
2166 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2167 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002168int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002169{
Paul Bakker23986e52011-04-24 08:57:21 +00002170 int ret;
2171 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002172 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002173
Hanno Becker73d7d792018-12-11 10:35:51 +00002174 MPI_VALIDATE_RET( G != NULL );
2175 MPI_VALIDATE_RET( A != NULL );
2176 MPI_VALIDATE_RET( B != NULL );
2177
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002178 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002180 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2181 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002182
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002183 lz = mbedtls_mpi_lsb( &TA );
2184 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002185
Paul Bakker66d5d072014-06-17 16:39:18 +02002186 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002187 lz = lzt;
2188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002189 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2190 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002191
Paul Bakker5121ce52009-01-03 21:22:43 +00002192 TA.s = TB.s = 1;
2193
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002194 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002195 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002196 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2197 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002198
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002199 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002200 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002201 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2202 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002203 }
2204 else
2205 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2207 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002208 }
2209 }
2210
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002211 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2212 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002213
2214cleanup:
2215
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002216 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002217
2218 return( ret );
2219}
2220
Paul Bakker33dc46b2014-04-30 16:11:39 +02002221/*
2222 * Fill X with size bytes of random.
2223 *
2224 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002225 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002226 * deterministic, eg for tests).
2227 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002228int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002229 int (*f_rng)(void *, unsigned char *, size_t),
2230 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002231{
Paul Bakker23986e52011-04-24 08:57:21 +00002232 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002233 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002234 size_t const overhead = ( limbs * ciL ) - size;
2235 unsigned char *Xp;
2236
Hanno Becker8ce11a32018-12-19 16:18:52 +00002237 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002238 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002239
Hanno Beckerda1655a2017-10-18 14:21:44 +01002240 /* Ensure that target MPI has exactly the necessary number of limbs */
2241 if( X->n != limbs )
2242 {
2243 mbedtls_mpi_free( X );
2244 mbedtls_mpi_init( X );
2245 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2246 }
2247 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002248
Hanno Beckerda1655a2017-10-18 14:21:44 +01002249 Xp = (unsigned char*) X->p;
2250 f_rng( p_rng, Xp + overhead, size );
2251
Hanno Becker2be8a552018-10-25 12:40:09 +01002252 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002253
2254cleanup:
2255 return( ret );
2256}
2257
Paul Bakker5121ce52009-01-03 21:22:43 +00002258/*
2259 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002261int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002262{
2263 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002265 MPI_VALIDATE_RET( X != NULL );
2266 MPI_VALIDATE_RET( A != NULL );
2267 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002268
Hanno Becker4bcb4912017-04-18 15:49:39 +01002269 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002270 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002271
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2273 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2274 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002275
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002276 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002277
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002278 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002279 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002280 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002281 goto cleanup;
2282 }
2283
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002284 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2285 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2286 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2287 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002288
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002289 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2290 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2291 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2292 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002293
2294 do
2295 {
2296 while( ( TU.p[0] & 1 ) == 0 )
2297 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002298 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002299
2300 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2301 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002302 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2303 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002304 }
2305
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002306 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2307 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002308 }
2309
2310 while( ( TV.p[0] & 1 ) == 0 )
2311 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002312 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002313
2314 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2315 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002316 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2317 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002318 }
2319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002320 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2321 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002322 }
2323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002324 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002325 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002326 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2327 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2328 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002329 }
2330 else
2331 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002332 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2333 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2334 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002335 }
2336 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002337 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002338
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002339 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2340 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2343 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002345 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
2347cleanup:
2348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002349 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2350 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2351 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002352
2353 return( ret );
2354}
2355
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002356#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002357
Paul Bakker5121ce52009-01-03 21:22:43 +00002358static const int small_prime[] =
2359{
2360 3, 5, 7, 11, 13, 17, 19, 23,
2361 29, 31, 37, 41, 43, 47, 53, 59,
2362 61, 67, 71, 73, 79, 83, 89, 97,
2363 101, 103, 107, 109, 113, 127, 131, 137,
2364 139, 149, 151, 157, 163, 167, 173, 179,
2365 181, 191, 193, 197, 199, 211, 223, 227,
2366 229, 233, 239, 241, 251, 257, 263, 269,
2367 271, 277, 281, 283, 293, 307, 311, 313,
2368 317, 331, 337, 347, 349, 353, 359, 367,
2369 373, 379, 383, 389, 397, 401, 409, 419,
2370 421, 431, 433, 439, 443, 449, 457, 461,
2371 463, 467, 479, 487, 491, 499, 503, 509,
2372 521, 523, 541, 547, 557, 563, 569, 571,
2373 577, 587, 593, 599, 601, 607, 613, 617,
2374 619, 631, 641, 643, 647, 653, 659, 661,
2375 673, 677, 683, 691, 701, 709, 719, 727,
2376 733, 739, 743, 751, 757, 761, 769, 773,
2377 787, 797, 809, 811, 821, 823, 827, 829,
2378 839, 853, 857, 859, 863, 877, 881, 883,
2379 887, 907, 911, 919, 929, 937, 941, 947,
2380 953, 967, 971, 977, 983, 991, 997, -103
2381};
2382
2383/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002384 * Small divisors test (X must be positive)
2385 *
2386 * Return values:
2387 * 0: no small factor (possible prime, more tests needed)
2388 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002389 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002390 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002391 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002392static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002393{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002394 int ret = 0;
2395 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002397
Paul Bakker5121ce52009-01-03 21:22:43 +00002398 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002399 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002400
2401 for( i = 0; small_prime[i] > 0; i++ )
2402 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002403 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002404 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002406 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002407
2408 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002409 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002410 }
2411
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002412cleanup:
2413 return( ret );
2414}
2415
2416/*
2417 * Miller-Rabin pseudo-primality test (HAC 4.24)
2418 */
Janos Follathda31fa12018-09-03 14:45:23 +01002419static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002420 int (*f_rng)(void *, unsigned char *, size_t),
2421 void *p_rng )
2422{
Pascal Junodb99183d2015-03-11 16:49:45 +01002423 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002424 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002425 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002426
Hanno Becker8ce11a32018-12-19 16:18:52 +00002427 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002428 MPI_VALIDATE_RET( f_rng != NULL );
2429
2430 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2431 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002432 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002433
Paul Bakker5121ce52009-01-03 21:22:43 +00002434 /*
2435 * W = |X| - 1
2436 * R = W >> lsb( W )
2437 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002438 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2439 s = mbedtls_mpi_lsb( &W );
2440 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2441 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002442
Janos Follathda31fa12018-09-03 14:45:23 +01002443 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002444 {
2445 /*
2446 * pick a random A, 1 < A < |X| - 1
2447 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002448 count = 0;
2449 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002450 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002451
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002452 j = mbedtls_mpi_bitlen( &A );
2453 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002454 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002455 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002456 }
2457
2458 if (count++ > 30) {
Jens Wiklanderdfd447e2019-01-17 13:30:57 +01002459 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2460 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002461 }
2462
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002463 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2464 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002465
2466 /*
2467 * A = A^R mod |X|
2468 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002469 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002471 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2472 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002473 continue;
2474
2475 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002476 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002477 {
2478 /*
2479 * A = A * A mod |X|
2480 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002481 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2482 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002484 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002485 break;
2486
2487 j++;
2488 }
2489
2490 /*
2491 * not prime if A != |X| - 1 or A == 1
2492 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002493 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2494 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002495 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002496 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002497 break;
2498 }
2499 }
2500
2501cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002502 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2503 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002504 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002505
2506 return( ret );
2507}
2508
2509/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002510 * Pseudo-primality test: small factors, then Miller-Rabin
2511 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002512int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2513 int (*f_rng)(void *, unsigned char *, size_t),
2514 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002515{
2516 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002517 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002518 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002519 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002520
2521 XX.s = 1;
2522 XX.n = X->n;
2523 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002525 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2526 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2527 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002529 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002530 return( 0 );
2531
2532 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2533 {
2534 if( ret == 1 )
2535 return( 0 );
2536
2537 return( ret );
2538 }
2539
Janos Follathda31fa12018-09-03 14:45:23 +01002540 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002541}
2542
Janos Follatha0b67c22018-09-18 14:48:23 +01002543#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002544/*
2545 * Pseudo-primality test, error probability 2^-80
2546 */
2547int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2548 int (*f_rng)(void *, unsigned char *, size_t),
2549 void *p_rng )
2550{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002551 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002552 MPI_VALIDATE_RET( f_rng != NULL );
2553
Janos Follatha0b67c22018-09-18 14:48:23 +01002554 /*
2555 * In the past our key generation aimed for an error rate of at most
2556 * 2^-80. Since this function is deprecated, aim for the same certainty
2557 * here as well.
2558 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002559 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002560}
Janos Follatha0b67c22018-09-18 14:48:23 +01002561#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002562
2563/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002564 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002565 *
Janos Follathf301d232018-08-14 13:34:01 +01002566 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2567 * be either 1024 bits or 1536 bits long, and flags must contain
2568 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002569 */
Janos Follath7c025a92018-08-14 11:08:41 +01002570int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002571 int (*f_rng)(void *, unsigned char *, size_t),
2572 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002573{
Jethro Beekman66689272018-02-14 19:24:10 -08002574#ifdef MBEDTLS_HAVE_INT64
2575// ceil(2^63.5)
2576#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2577#else
2578// ceil(2^31.5)
2579#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2580#endif
2581 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002582 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002583 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002584 mbedtls_mpi_uint r;
2585 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002586
Hanno Becker8ce11a32018-12-19 16:18:52 +00002587 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002588 MPI_VALIDATE_RET( f_rng != NULL );
2589
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002590 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2591 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002593 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002594
2595 n = BITS_TO_LIMBS( nbits );
2596
Janos Follathda31fa12018-09-03 14:45:23 +01002597 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2598 {
2599 /*
2600 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2601 */
2602 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2603 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2604 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2605 }
2606 else
2607 {
2608 /*
2609 * 2^-100 error probability, number of rounds computed based on HAC,
2610 * fact 4.48
2611 */
2612 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2613 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2614 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2615 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2616 }
2617
Jethro Beekman66689272018-02-14 19:24:10 -08002618 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002619 {
Jethro Beekman66689272018-02-14 19:24:10 -08002620 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2621 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2622 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2623
2624 k = n * biL;
2625 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2626 X->p[0] |= 1;
2627
Janos Follath7c025a92018-08-14 11:08:41 +01002628 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002629 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002630 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002631
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002632 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002633 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002634 }
Jethro Beekman66689272018-02-14 19:24:10 -08002635 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002636 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002637 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002638 * An necessary condition for Y and X = 2Y + 1 to be prime
2639 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2640 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002641 */
Jethro Beekman66689272018-02-14 19:24:10 -08002642
2643 X->p[0] |= 2;
2644
2645 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2646 if( r == 0 )
2647 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2648 else if( r == 1 )
2649 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2650
2651 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2652 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2653 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2654
2655 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002656 {
Jethro Beekman66689272018-02-14 19:24:10 -08002657 /*
2658 * First, check small factors for X and Y
2659 * before doing Miller-Rabin on any of them
2660 */
2661 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2662 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002663 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002664 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002665 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002666 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002667 goto cleanup;
2668
2669 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2670 goto cleanup;
2671
2672 /*
2673 * Next candidates. We want to preserve Y = (X-1) / 2 and
2674 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2675 * so up Y by 6 and X by 12.
2676 */
2677 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2678 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002679 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002680 }
2681 }
2682
2683cleanup:
2684
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002685 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002686
2687 return( ret );
2688}
2689
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002690#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002692#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002693
Paul Bakker23986e52011-04-24 08:57:21 +00002694#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002695
2696static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2697{
2698 { 693, 609, 21 },
2699 { 1764, 868, 28 },
2700 { 768454923, 542167814, 1 }
2701};
2702
Paul Bakker5121ce52009-01-03 21:22:43 +00002703/*
2704 * Checkup routine
2705 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002706int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002707{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002708 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002709 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002710
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002711 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2712 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002713
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002714 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002715 "EFE021C2645FD1DC586E69184AF4A31E" \
2716 "D5F53E93B5F123FA41680867BA110131" \
2717 "944FE7952E2517337780CB0DB80E61AA" \
2718 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2719
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002720 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002721 "B2E7EFD37075B9F03FF989C7C5051C20" \
2722 "34D2A323810251127E7BF8625A4F49A5" \
2723 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2724 "5B5C25763222FEFCCFC38B832366C29E" ) );
2725
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002726 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002727 "0066A198186C18C10B2F5ED9B522752A" \
2728 "9830B69916E535C8F047518A889A43A5" \
2729 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2730
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002731 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002732
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002733 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002734 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2735 "9E857EA95A03512E2BAE7391688D264A" \
2736 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2737 "8001B72E848A38CAE1C65F78E56ABDEF" \
2738 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2739 "ECF677152EF804370C1A305CAF3B5BF1" \
2740 "30879B56C61DE584A0F53A2447A51E" ) );
2741
2742 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002743 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002744
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002745 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002746 {
2747 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002748 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002749
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002750 ret = 1;
2751 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002752 }
2753
2754 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002755 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002756
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002757 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002758
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002759 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002760 "256567336059E52CAE22925474705F39A94" ) );
2761
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002762 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002763 "6613F26162223DF488E9CD48CC132C7A" \
2764 "0AC93C701B001B092E4E5B9F73BCD27B" \
2765 "9EE50D0657C77F374E903CDFA4C642" ) );
2766
2767 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002768 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002769
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002770 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2771 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002772 {
2773 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002774 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002775
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002776 ret = 1;
2777 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002778 }
2779
2780 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002781 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002782
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002783 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002784
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002785 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002786 "36E139AEA55215609D2816998ED020BB" \
2787 "BD96C37890F65171D948E9BC7CBAA4D9" \
2788 "325D24D6A3C12710F10A09FA08AB87" ) );
2789
2790 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002791 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002792
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002793 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002794 {
2795 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002796 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002797
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002798 ret = 1;
2799 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002800 }
2801
2802 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002803 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002804
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002805 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002806
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002807 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002808 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2809 "C3DBA76456363A10869622EAC2DD84EC" \
2810 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2811
2812 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002813 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002814
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002815 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002816 {
2817 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002818 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002819
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002820 ret = 1;
2821 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002822 }
2823
2824 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002825 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002826
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002827 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002828 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002829
Paul Bakker66d5d072014-06-17 16:39:18 +02002830 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002831 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002832 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2833 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002834
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002835 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002836
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002837 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002838 {
2839 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002840 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002841
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002842 ret = 1;
2843 goto cleanup;
2844 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002845 }
2846
2847 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002848 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002849
Paul Bakker5121ce52009-01-03 21:22:43 +00002850cleanup:
2851
2852 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002853 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002854
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002855 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2856 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002857
2858 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002859 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002860
2861 return( ret );
2862}
2863
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002864#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002865
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002866#endif /* MBEDTLS_BIGNUM_C */