blob: d28d3beb7030b850d3b3cc029d455d2de9e6727a [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050048#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000049
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <string.h>
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020054#else
Rich Evans00ab4702015-02-06 13:43:58 +000055#include <stdio.h>
56#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020058#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020060#endif
61
Hanno Becker73d7d792018-12-11 10:35:51 +000062#define MPI_VALIDATE_RET( cond ) \
63 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
64#define MPI_VALIDATE( cond ) \
65 MBEDTLS_INTERNAL_VALIDATE( cond )
66
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020067#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000068#define biL (ciL << 3) /* bits in limb */
69#define biH (ciL << 2) /* half limb size */
70
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010071#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
72
Paul Bakker5121ce52009-01-03 21:22:43 +000073/*
74 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020075 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000076 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020077#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
78#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000079
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050080/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050081static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
82{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050083 mbedtls_platform_zeroize( v, ciL * n );
84}
85
Paul Bakker5121ce52009-01-03 21:22:43 +000086/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000088 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000090{
Hanno Becker73d7d792018-12-11 10:35:51 +000091 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000092
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 X->s = 1;
94 X->n = 0;
95 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000096}
97
98/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000099 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000103 if( X == NULL )
104 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000105
Paul Bakker6c591fa2011-05-05 11:49:20 +0000106 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000107 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200108 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000110 }
111
Paul Bakker6c591fa2011-05-05 11:49:20 +0000112 X->s = 1;
113 X->n = 0;
114 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000115}
116
117/*
118 * Enlarge to the specified number of limbs
119 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000121{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000123 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200126 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000127
Paul Bakker5121ce52009-01-03 21:22:43 +0000128 if( X->n < nblimbs )
129 {
Simon Butcher29176892016-05-20 00:19:09 +0100130 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200131 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000132
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 if( X->p != NULL )
134 {
135 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200136 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000138 }
139
140 X->n = nblimbs;
141 X->p = p;
142 }
143
144 return( 0 );
145}
146
147/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100148 * Resize down as much as possible,
149 * while keeping at least the specified number of limbs
150 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000155 MPI_VALIDATE_RET( X != NULL );
156
157 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
158 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100159
160 /* Actually resize up in this case */
161 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163
164 for( i = X->n - 1; i > 0; i-- )
165 if( X->p[i] != 0 )
166 break;
167 i++;
168
169 if( i < nblimbs )
170 i = nblimbs;
171
Simon Butcher29176892016-05-20 00:19:09 +0100172 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200173 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100174
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175 if( X->p != NULL )
176 {
177 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200178 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100180 }
181
182 X->n = i;
183 X->p = p;
184
185 return( 0 );
186}
187
188/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000189 * Copy the contents of Y into X
190 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000192{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100193 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000194 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000195 MPI_VALIDATE_RET( X != NULL );
196 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000197
198 if( X == Y )
199 return( 0 );
200
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200201 if( Y->p == NULL )
202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200204 return( 0 );
205 }
206
Paul Bakker5121ce52009-01-03 21:22:43 +0000207 for( i = Y->n - 1; i > 0; i-- )
208 if( Y->p[i] != 0 )
209 break;
210 i++;
211
212 X->s = Y->s;
213
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100214 if( X->n < i )
215 {
216 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
217 }
218 else
219 {
220 memset( X->p + i, 0, ( X->n - i ) * ciL );
221 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
Paul Bakker5121ce52009-01-03 21:22:43 +0000223 memcpy( X->p, Y->p, i * ciL );
224
225cleanup:
226
227 return( ret );
228}
229
230/*
231 * Swap the contents of X and Y
232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000234{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000236 MPI_VALIDATE( X != NULL );
237 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 memcpy( &T, X, sizeof( mbedtls_mpi ) );
240 memcpy( X, Y, sizeof( mbedtls_mpi ) );
241 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000242}
243
244/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100245 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100246 * about whether the assignment was made or not.
247 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100248 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250{
251 int ret = 0;
252 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000253 MPI_VALIDATE_RET( X != NULL );
254 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100255
Pascal Junodb99183d2015-03-11 16:49:45 +0100256 /* make sure assign is 0 or 1 in a time-constant manner */
257 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100260
Paul Bakker66d5d072014-06-17 16:39:18 +0200261 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100262
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100263 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200264 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100265
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100266 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200267 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100268
269cleanup:
270 return( ret );
271}
272
273/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274 * Conditionally swap X and Y, without leaking information
275 * about whether the swap was made or not.
276 * Here it is not ok to simply swap the pointers, which whould lead to
277 * different memory access patterns when X and Y are used afterwards.
278 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100280{
281 int ret, s;
282 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000284 MPI_VALIDATE_RET( X != NULL );
285 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286
287 if( X == Y )
288 return( 0 );
289
Pascal Junodb99183d2015-03-11 16:49:45 +0100290 /* make sure swap is 0 or 1 in a time-constant manner */
291 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100295
296 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200297 X->s = X->s * ( 1 - swap ) + Y->s * swap;
298 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100299
300
301 for( i = 0; i < X->n; i++ )
302 {
303 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200304 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
305 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100306 }
307
308cleanup:
309 return( ret );
310}
311
312/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000313 * Set value from integer
314 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000316{
317 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +0000318 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200320 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000321 memset( X->p, 0, X->n * ciL );
322
323 X->p[0] = ( z < 0 ) ? -z : z;
324 X->s = ( z < 0 ) ? -1 : 1;
325
326cleanup:
327
328 return( ret );
329}
330
331/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332 * Get a specific bit
333 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000335{
Hanno Becker73d7d792018-12-11 10:35:51 +0000336 MPI_VALIDATE_RET( X != NULL );
337
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338 if( X->n * biL <= pos )
339 return( 0 );
340
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200341 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000342}
343
Gilles Peskine11cdb052018-11-20 16:47:47 +0100344/* Get a specific byte, without range checks. */
345#define GET_BYTE( X, i ) \
346 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
347
Paul Bakker2f5947e2011-05-18 15:47:11 +0000348/*
349 * Set a bit to a specific value of 0 or 1
350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000352{
353 int ret = 0;
354 size_t off = pos / biL;
355 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000356 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000357
358 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200360
Paul Bakker2f5947e2011-05-18 15:47:11 +0000361 if( X->n * biL <= pos )
362 {
363 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200364 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000367 }
368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
370 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000371
372cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200373
Paul Bakker2f5947e2011-05-18 15:47:11 +0000374 return( ret );
375}
376
377/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200378 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000381{
Paul Bakker23986e52011-04-24 08:57:21 +0000382 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000383 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000384
385 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000386 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
388 return( count );
389
390 return( 0 );
391}
392
393/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000394 * Count leading zero bits in a given integer
395 */
396static size_t mbedtls_clz( const mbedtls_mpi_uint x )
397{
398 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100399 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000400
401 for( j = 0; j < biL; j++ )
402 {
403 if( x & mask ) break;
404
405 mask >>= 1;
406 }
407
408 return j;
409}
410
411/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200412 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000413 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200414size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000415{
Paul Bakker23986e52011-04-24 08:57:21 +0000416 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200418 if( X->n == 0 )
419 return( 0 );
420
Paul Bakker5121ce52009-01-03 21:22:43 +0000421 for( i = X->n - 1; i > 0; i-- )
422 if( X->p[i] != 0 )
423 break;
424
Simon Butcher15b15d12015-11-26 19:35:03 +0000425 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
Paul Bakker23986e52011-04-24 08:57:21 +0000427 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000428}
429
430/*
431 * Return the total size in bytes
432 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000434{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200435 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000436}
437
438/*
439 * Convert an ASCII character to digit value
440 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000442{
443 *d = 255;
444
445 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
446 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
447 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 if( *d >= (mbedtls_mpi_uint) radix )
450 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000451
452 return( 0 );
453}
454
455/*
456 * Import from an ASCII string
457 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000459{
Paul Bakker23986e52011-04-24 08:57:21 +0000460 int ret;
461 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 mbedtls_mpi_uint d;
463 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000464 MPI_VALIDATE_RET( X != NULL );
465 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000466
467 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000468 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000471
Paul Bakkerff60ee62010-03-16 21:09:09 +0000472 slen = strlen( s );
473
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 if( radix == 16 )
475 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100476 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200477 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
478
Paul Bakkerff60ee62010-03-16 21:09:09 +0000479 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
482 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
Paul Bakker23986e52011-04-24 08:57:21 +0000484 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000485 {
Paul Bakker23986e52011-04-24 08:57:21 +0000486 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000487 {
488 X->s = -1;
489 break;
490 }
491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200493 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494 }
495 }
496 else
497 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
Paul Bakkerff60ee62010-03-16 21:09:09 +0000500 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000501 {
502 if( i == 0 && s[i] == '-' )
503 {
504 X->s = -1;
505 continue;
506 }
507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
509 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000510
511 if( X->s == 1 )
512 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000514 }
515 else
516 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000518 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000519 }
520 }
521
522cleanup:
523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000525
526 return( ret );
527}
528
529/*
Ron Eldora16fa292018-11-20 14:07:01 +0200530 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000531 */
Ron Eldora16fa292018-11-20 14:07:01 +0200532static int mpi_write_hlp( mbedtls_mpi *X, int radix,
533 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000534{
535 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200537 size_t length = 0;
538 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
Ron Eldora16fa292018-11-20 14:07:01 +0200540 do
541 {
542 if( length >= buflen )
543 {
544 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
545 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000546
Ron Eldora16fa292018-11-20 14:07:01 +0200547 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
548 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
549 /*
550 * Write the residue in the current position, as an ASCII character.
551 */
552 if( r < 0xA )
553 *(--p_end) = (char)( '0' + r );
554 else
555 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000556
Ron Eldora16fa292018-11-20 14:07:01 +0200557 length++;
558 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000559
Ron Eldora16fa292018-11-20 14:07:01 +0200560 memmove( *p, p_end, length );
561 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000562
563cleanup:
564
565 return( ret );
566}
567
568/*
569 * Export into an ASCII string
570 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100571int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
572 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000573{
Paul Bakker23986e52011-04-24 08:57:21 +0000574 int ret = 0;
575 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000576 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000578 MPI_VALIDATE_RET( X != NULL );
579 MPI_VALIDATE_RET( olen != NULL );
580 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000581
582 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000583 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200585 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000586 if( radix >= 4 ) n >>= 1;
587 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000588 /*
589 * Round up the buffer length to an even value to ensure that there is
590 * enough room for hexadecimal values that can be represented in an odd
591 * number of digits.
592 */
593 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000594
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100595 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000596 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100597 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000599 }
600
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100601 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000603
604 if( X->s == -1 )
605 *p++ = '-';
606
607 if( radix == 16 )
608 {
Paul Bakker23986e52011-04-24 08:57:21 +0000609 int c;
610 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000611
Paul Bakker23986e52011-04-24 08:57:21 +0000612 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000613 {
Paul Bakker23986e52011-04-24 08:57:21 +0000614 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000615 {
Paul Bakker23986e52011-04-24 08:57:21 +0000616 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000617
Paul Bakker6c343d72014-07-10 14:36:19 +0200618 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000619 continue;
620
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000621 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000622 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 k = 1;
624 }
625 }
626 }
627 else
628 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000630
631 if( T.s == -1 )
632 T.s = 1;
633
Ron Eldora16fa292018-11-20 14:07:01 +0200634 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000635 }
636
637 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100638 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000639
640cleanup:
641
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000643
644 return( ret );
645}
646
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200647#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000648/*
649 * Read X from an opened file
650 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000652{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000654 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000655 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000656 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000657 * Buffer should have space for (short) label and decimal formatted MPI,
658 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000659 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200660 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000661
Hanno Becker73d7d792018-12-11 10:35:51 +0000662 MPI_VALIDATE_RET( X != NULL );
663 MPI_VALIDATE_RET( fin != NULL );
664
665 if( radix < 2 || radix > 16 )
666 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
667
Paul Bakker5121ce52009-01-03 21:22:43 +0000668 memset( s, 0, sizeof( s ) );
669 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000671
672 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000673 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000675
Hanno Beckerb2034b72017-04-26 11:46:46 +0100676 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
677 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000678
679 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100680 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000681 if( mpi_get_digit( &d, radix, *p ) != 0 )
682 break;
683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000685}
686
687/*
688 * Write X into an opened file (or stdout if fout == NULL)
689 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000691{
Paul Bakker23986e52011-04-24 08:57:21 +0000692 int ret;
693 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000694 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000695 * Buffer should have space for (short) label and decimal formatted MPI,
696 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000697 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000699 MPI_VALIDATE_RET( X != NULL );
700
701 if( radix < 2 || radix > 16 )
702 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000703
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100704 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000705
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100706 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
708 if( p == NULL ) p = "";
709
710 plen = strlen( p );
711 slen = strlen( s );
712 s[slen++] = '\r';
713 s[slen++] = '\n';
714
715 if( fout != NULL )
716 {
717 if( fwrite( p, 1, plen, fout ) != plen ||
718 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000720 }
721 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000723
724cleanup:
725
726 return( ret );
727}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000729
Hanno Beckerda1655a2017-10-18 14:21:44 +0100730
731/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
732 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000733
734static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
735{
736 uint8_t i;
737 mbedtls_mpi_uint tmp = 0;
738 /* This works regardless of the endianness. */
739 for( i = 0; i < ciL; i++, x >>= 8 )
740 tmp |= ( x & 0xFF ) << ( ( ciL - 1 - i ) << 3 );
741 return( tmp );
742}
743
744static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
745{
746#if defined(__BYTE_ORDER__)
747
748/* Nothing to do on bigendian systems. */
749#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
750 return( x );
751#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
752
753#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
754
755/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000756#if defined(__GNUC__) && defined(__GNUC_PREREQ)
757#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000758#define have_bswap
759#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000760#endif
761
762#if defined(__clang__) && defined(__has_builtin)
763#if __has_builtin(__builtin_bswap32) && \
764 __has_builtin(__builtin_bswap64)
765#define have_bswap
766#endif
767#endif
768
Hanno Beckerf8720072018-11-08 11:53:49 +0000769#if defined(have_bswap)
770 /* The compiler is hopefully able to statically evaluate this! */
771 switch( sizeof(mbedtls_mpi_uint) )
772 {
773 case 4:
774 return( __builtin_bswap32(x) );
775 case 8:
776 return( __builtin_bswap64(x) );
777 }
778#endif
779#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
780#endif /* __BYTE_ORDER__ */
781
782 /* Fall back to C-based reordering if we don't know the byte order
783 * or we couldn't use a compiler-specific builtin. */
784 return( mpi_uint_bigendian_to_host_c( x ) );
785}
786
Hanno Becker2be8a552018-10-25 12:40:09 +0100787static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100788{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100789 mbedtls_mpi_uint *cur_limb_left;
790 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100791 if( limbs == 0 )
792 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100793
794 /*
795 * Traverse limbs and
796 * - adapt byte-order in each limb
797 * - swap the limbs themselves.
798 * For that, simultaneously traverse the limbs from left to right
799 * and from right to left, as long as the left index is not bigger
800 * than the right index (it's not a problem if limbs is odd and the
801 * indices coincide in the last iteration).
802 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100803 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
804 cur_limb_left <= cur_limb_right;
805 cur_limb_left++, cur_limb_right-- )
806 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000807 mbedtls_mpi_uint tmp;
808 /* Note that if cur_limb_left == cur_limb_right,
809 * this code effectively swaps the bytes only once. */
810 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
811 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
812 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100813 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100814}
815
Paul Bakker5121ce52009-01-03 21:22:43 +0000816/*
Janos Follatha778a942019-02-13 10:28:28 +0000817 * Import X from unsigned binary data, little endian
818 */
819int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
820 const unsigned char *buf, size_t buflen )
821{
822 int ret;
823 size_t i;
824 size_t const limbs = CHARS_TO_LIMBS( buflen );
825
826 /* Ensure that target MPI has exactly the necessary number of limbs */
827 if( X->n != limbs )
828 {
829 mbedtls_mpi_free( X );
830 mbedtls_mpi_init( X );
831 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
832 }
833
834 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
835
836 for( i = 0; i < buflen; i++ )
837 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
838
839cleanup:
840
841 return( ret );
842}
843
844/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000845 * Import X from unsigned binary data, big endian
846 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200847int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000848{
Paul Bakker23986e52011-04-24 08:57:21 +0000849 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100850 size_t const limbs = CHARS_TO_LIMBS( buflen );
851 size_t const overhead = ( limbs * ciL ) - buflen;
852 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000853
Hanno Becker8ce11a32018-12-19 16:18:52 +0000854 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000855 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
856
Hanno Becker073c1992017-10-17 15:17:27 +0100857 /* Ensure that target MPI has exactly the necessary number of limbs */
858 if( X->n != limbs )
859 {
860 mbedtls_mpi_free( X );
861 mbedtls_mpi_init( X );
862 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
863 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200864 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000865
Hanno Becker0e810b92019-01-03 17:13:11 +0000866 /* Avoid calling `memcpy` with NULL source argument,
867 * even if buflen is 0. */
868 if( buf != NULL )
869 {
870 Xp = (unsigned char*) X->p;
871 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100872
Hanno Becker0e810b92019-01-03 17:13:11 +0000873 mpi_bigendian_to_host( X->p, limbs );
874 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000875
876cleanup:
877
878 return( ret );
879}
880
881/*
882 * Export X into unsigned binary data, big endian
883 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100884int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
885 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000886{
Hanno Becker73d7d792018-12-11 10:35:51 +0000887 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100888 size_t bytes_to_copy;
889 unsigned char *p;
890 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000891
Hanno Becker73d7d792018-12-11 10:35:51 +0000892 MPI_VALIDATE_RET( X != NULL );
893 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
894
895 stored_bytes = X->n * ciL;
896
Gilles Peskine11cdb052018-11-20 16:47:47 +0100897 if( stored_bytes < buflen )
898 {
899 /* There is enough space in the output buffer. Write initial
900 * null bytes and record the position at which to start
901 * writing the significant bytes. In this case, the execution
902 * trace of this function does not depend on the value of the
903 * number. */
904 bytes_to_copy = stored_bytes;
905 p = buf + buflen - stored_bytes;
906 memset( buf, 0, buflen - stored_bytes );
907 }
908 else
909 {
910 /* The output buffer is smaller than the allocated size of X.
911 * However X may fit if its leading bytes are zero. */
912 bytes_to_copy = buflen;
913 p = buf;
914 for( i = bytes_to_copy; i < stored_bytes; i++ )
915 {
916 if( GET_BYTE( X, i ) != 0 )
917 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
918 }
919 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000920
Gilles Peskine11cdb052018-11-20 16:47:47 +0100921 for( i = 0; i < bytes_to_copy; i++ )
922 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000923
924 return( 0 );
925}
926
927/*
928 * Left-shift: X <<= count
929 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200930int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000931{
Paul Bakker23986e52011-04-24 08:57:21 +0000932 int ret;
933 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200934 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000935 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000936
937 v0 = count / (biL );
938 t1 = count & (biL - 1);
939
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200940 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000941
Paul Bakkerf9688572011-05-05 10:00:45 +0000942 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200943 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000944
945 ret = 0;
946
947 /*
948 * shift by count / limb_size
949 */
950 if( v0 > 0 )
951 {
Paul Bakker23986e52011-04-24 08:57:21 +0000952 for( i = X->n; i > v0; i-- )
953 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000954
Paul Bakker23986e52011-04-24 08:57:21 +0000955 for( ; i > 0; i-- )
956 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000957 }
958
959 /*
960 * shift by count % limb_size
961 */
962 if( t1 > 0 )
963 {
964 for( i = v0; i < X->n; i++ )
965 {
966 r1 = X->p[i] >> (biL - t1);
967 X->p[i] <<= t1;
968 X->p[i] |= r0;
969 r0 = r1;
970 }
971 }
972
973cleanup:
974
975 return( ret );
976}
977
978/*
979 * Right-shift: X >>= count
980 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200981int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000982{
Paul Bakker23986e52011-04-24 08:57:21 +0000983 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200984 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000985 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000986
987 v0 = count / biL;
988 v1 = count & (biL - 1);
989
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100990 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200991 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100992
Paul Bakker5121ce52009-01-03 21:22:43 +0000993 /*
994 * shift by count / limb_size
995 */
996 if( v0 > 0 )
997 {
998 for( i = 0; i < X->n - v0; i++ )
999 X->p[i] = X->p[i + v0];
1000
1001 for( ; i < X->n; i++ )
1002 X->p[i] = 0;
1003 }
1004
1005 /*
1006 * shift by count % limb_size
1007 */
1008 if( v1 > 0 )
1009 {
Paul Bakker23986e52011-04-24 08:57:21 +00001010 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001011 {
Paul Bakker23986e52011-04-24 08:57:21 +00001012 r1 = X->p[i - 1] << (biL - v1);
1013 X->p[i - 1] >>= v1;
1014 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001015 r0 = r1;
1016 }
1017 }
1018
1019 return( 0 );
1020}
1021
1022/*
1023 * Compare unsigned values
1024 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001025int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001026{
Paul Bakker23986e52011-04-24 08:57:21 +00001027 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001028 MPI_VALIDATE_RET( X != NULL );
1029 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001030
Paul Bakker23986e52011-04-24 08:57:21 +00001031 for( i = X->n; i > 0; i-- )
1032 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001033 break;
1034
Paul Bakker23986e52011-04-24 08:57:21 +00001035 for( j = Y->n; j > 0; j-- )
1036 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001037 break;
1038
Paul Bakker23986e52011-04-24 08:57:21 +00001039 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001040 return( 0 );
1041
1042 if( i > j ) return( 1 );
1043 if( j > i ) return( -1 );
1044
Paul Bakker23986e52011-04-24 08:57:21 +00001045 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001046 {
Paul Bakker23986e52011-04-24 08:57:21 +00001047 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1048 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001049 }
1050
1051 return( 0 );
1052}
1053
1054/*
1055 * Compare signed values
1056 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001057int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001058{
Paul Bakker23986e52011-04-24 08:57:21 +00001059 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001060 MPI_VALIDATE_RET( X != NULL );
1061 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001062
Paul Bakker23986e52011-04-24 08:57:21 +00001063 for( i = X->n; i > 0; i-- )
1064 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001065 break;
1066
Paul Bakker23986e52011-04-24 08:57:21 +00001067 for( j = Y->n; j > 0; j-- )
1068 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001069 break;
1070
Paul Bakker23986e52011-04-24 08:57:21 +00001071 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001072 return( 0 );
1073
1074 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001075 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001076
1077 if( X->s > 0 && Y->s < 0 ) return( 1 );
1078 if( Y->s > 0 && X->s < 0 ) return( -1 );
1079
Paul Bakker23986e52011-04-24 08:57:21 +00001080 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001081 {
Paul Bakker23986e52011-04-24 08:57:21 +00001082 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1083 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001084 }
1085
1086 return( 0 );
1087}
1088
1089/*
1090 * Compare signed values
1091 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001092int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001093{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001094 mbedtls_mpi Y;
1095 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001096 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001097
1098 *p = ( z < 0 ) ? -z : z;
1099 Y.s = ( z < 0 ) ? -1 : 1;
1100 Y.n = 1;
1101 Y.p = p;
1102
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001103 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001104}
1105
1106/*
1107 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1108 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001109int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001110{
Paul Bakker23986e52011-04-24 08:57:21 +00001111 int ret;
1112 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001113 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001114 MPI_VALIDATE_RET( X != NULL );
1115 MPI_VALIDATE_RET( A != NULL );
1116 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001117
1118 if( X == B )
1119 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001120 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001121 }
1122
1123 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001124 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001125
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001126 /*
1127 * X should always be positive as a result of unsigned additions.
1128 */
1129 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001130
Paul Bakker23986e52011-04-24 08:57:21 +00001131 for( j = B->n; j > 0; j-- )
1132 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001133 break;
1134
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001135 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001136
1137 o = B->p; p = X->p; c = 0;
1138
Janos Follath6c922682015-10-30 17:43:11 +01001139 /*
1140 * tmp is used because it might happen that p == o
1141 */
Paul Bakker23986e52011-04-24 08:57:21 +00001142 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001143 {
Janos Follath6c922682015-10-30 17:43:11 +01001144 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001145 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001146 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001147 }
1148
1149 while( c != 0 )
1150 {
1151 if( i >= X->n )
1152 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001153 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001154 p = X->p + i;
1155 }
1156
Paul Bakker2d319fd2012-09-16 21:34:26 +00001157 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001158 }
1159
1160cleanup:
1161
1162 return( ret );
1163}
1164
1165/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001166 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001167 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001168static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001169{
Paul Bakker23986e52011-04-24 08:57:21 +00001170 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001171 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001172
1173 for( i = c = 0; i < n; i++, s++, d++ )
1174 {
1175 z = ( *d < c ); *d -= c;
1176 c = ( *d < *s ) + z; *d -= *s;
1177 }
1178
1179 while( c != 0 )
1180 {
1181 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001182 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001183 }
1184}
1185
1186/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001187 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001188 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001189int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001190{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001191 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001192 int ret;
1193 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001194 MPI_VALIDATE_RET( X != NULL );
1195 MPI_VALIDATE_RET( A != NULL );
1196 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001197
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001198 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1199 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001201 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001202
1203 if( X == B )
1204 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001205 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001206 B = &TB;
1207 }
1208
1209 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001210 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001211
Paul Bakker1ef7a532009-06-20 10:50:55 +00001212 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001213 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001214 */
1215 X->s = 1;
1216
Paul Bakker5121ce52009-01-03 21:22:43 +00001217 ret = 0;
1218
Paul Bakker23986e52011-04-24 08:57:21 +00001219 for( n = B->n; n > 0; n-- )
1220 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001221 break;
1222
Paul Bakker23986e52011-04-24 08:57:21 +00001223 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001224
1225cleanup:
1226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001227 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001228
1229 return( ret );
1230}
1231
1232/*
1233 * Signed addition: X = A + B
1234 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001235int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001236{
Hanno Becker73d7d792018-12-11 10:35:51 +00001237 int ret, s;
1238 MPI_VALIDATE_RET( X != NULL );
1239 MPI_VALIDATE_RET( A != NULL );
1240 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001241
Hanno Becker73d7d792018-12-11 10:35:51 +00001242 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001243 if( A->s * B->s < 0 )
1244 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001245 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001246 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001247 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001248 X->s = s;
1249 }
1250 else
1251 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001252 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001253 X->s = -s;
1254 }
1255 }
1256 else
1257 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001258 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001259 X->s = s;
1260 }
1261
1262cleanup:
1263
1264 return( ret );
1265}
1266
1267/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001268 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001269 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001270int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001271{
Hanno Becker73d7d792018-12-11 10:35:51 +00001272 int ret, s;
1273 MPI_VALIDATE_RET( X != NULL );
1274 MPI_VALIDATE_RET( A != NULL );
1275 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001276
Hanno Becker73d7d792018-12-11 10:35:51 +00001277 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001278 if( A->s * B->s > 0 )
1279 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001280 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001281 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001282 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001283 X->s = s;
1284 }
1285 else
1286 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001287 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001288 X->s = -s;
1289 }
1290 }
1291 else
1292 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001293 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001294 X->s = s;
1295 }
1296
1297cleanup:
1298
1299 return( ret );
1300}
1301
1302/*
1303 * Signed addition: X = A + b
1304 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001305int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001306{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001307 mbedtls_mpi _B;
1308 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001309 MPI_VALIDATE_RET( X != NULL );
1310 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001311
1312 p[0] = ( b < 0 ) ? -b : b;
1313 _B.s = ( b < 0 ) ? -1 : 1;
1314 _B.n = 1;
1315 _B.p = p;
1316
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001317 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001318}
1319
1320/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001321 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001322 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001323int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001324{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001325 mbedtls_mpi _B;
1326 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001327 MPI_VALIDATE_RET( X != NULL );
1328 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001329
1330 p[0] = ( b < 0 ) ? -b : b;
1331 _B.s = ( b < 0 ) ? -1 : 1;
1332 _B.n = 1;
1333 _B.p = p;
1334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001335 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001336}
1337
1338/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001339 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001340 */
1341static
1342#if defined(__APPLE__) && defined(__arm__)
1343/*
1344 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1345 * appears to need this to prevent bad ARM code generation at -O3.
1346 */
1347__attribute__ ((noinline))
1348#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001349void 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 +00001350{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001351 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001352
1353#if defined(MULADDC_HUIT)
1354 for( ; i >= 8; i -= 8 )
1355 {
1356 MULADDC_INIT
1357 MULADDC_HUIT
1358 MULADDC_STOP
1359 }
1360
1361 for( ; i > 0; i-- )
1362 {
1363 MULADDC_INIT
1364 MULADDC_CORE
1365 MULADDC_STOP
1366 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001367#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001368 for( ; i >= 16; i -= 16 )
1369 {
1370 MULADDC_INIT
1371 MULADDC_CORE MULADDC_CORE
1372 MULADDC_CORE MULADDC_CORE
1373 MULADDC_CORE MULADDC_CORE
1374 MULADDC_CORE MULADDC_CORE
1375
1376 MULADDC_CORE MULADDC_CORE
1377 MULADDC_CORE MULADDC_CORE
1378 MULADDC_CORE MULADDC_CORE
1379 MULADDC_CORE MULADDC_CORE
1380 MULADDC_STOP
1381 }
1382
1383 for( ; i >= 8; i -= 8 )
1384 {
1385 MULADDC_INIT
1386 MULADDC_CORE MULADDC_CORE
1387 MULADDC_CORE MULADDC_CORE
1388
1389 MULADDC_CORE MULADDC_CORE
1390 MULADDC_CORE MULADDC_CORE
1391 MULADDC_STOP
1392 }
1393
1394 for( ; i > 0; i-- )
1395 {
1396 MULADDC_INIT
1397 MULADDC_CORE
1398 MULADDC_STOP
1399 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001400#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001401
1402 t++;
1403
1404 do {
1405 *d += c; c = ( *d < c ); d++;
1406 }
1407 while( c != 0 );
1408}
1409
1410/*
1411 * Baseline multiplication: X = A * B (HAC 14.12)
1412 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001413int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001414{
Paul Bakker23986e52011-04-24 08:57:21 +00001415 int ret;
1416 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001417 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001418 MPI_VALIDATE_RET( X != NULL );
1419 MPI_VALIDATE_RET( A != NULL );
1420 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001421
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001422 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001424 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1425 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001426
Paul Bakker23986e52011-04-24 08:57:21 +00001427 for( i = A->n; i > 0; i-- )
1428 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001429 break;
1430
Paul Bakker23986e52011-04-24 08:57:21 +00001431 for( j = B->n; j > 0; j-- )
1432 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001433 break;
1434
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001435 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1436 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001437
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001438 for( ; j > 0; j-- )
1439 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001440
1441 X->s = A->s * B->s;
1442
1443cleanup:
1444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001445 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001446
1447 return( ret );
1448}
1449
1450/*
1451 * Baseline multiplication: X = A * b
1452 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001453int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001454{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001455 mbedtls_mpi _B;
1456 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001457 MPI_VALIDATE_RET( X != NULL );
1458 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001459
1460 _B.s = 1;
1461 _B.n = 1;
1462 _B.p = p;
1463 p[0] = b;
1464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001465 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001466}
1467
1468/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001469 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1470 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001471 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001472static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1473 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001474{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001475#if defined(MBEDTLS_HAVE_UDBL)
1476 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001477#else
Simon Butcher9803d072016-01-03 00:24:34 +00001478 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1479 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001480 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1481 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001482 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001483#endif
1484
Simon Butcher15b15d12015-11-26 19:35:03 +00001485 /*
1486 * Check for overflow
1487 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001488 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001489 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001490 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001491
Simon Butcherf5ba0452015-12-27 23:01:55 +00001492 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001493 }
1494
1495#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001496 dividend = (mbedtls_t_udbl) u1 << biL;
1497 dividend |= (mbedtls_t_udbl) u0;
1498 quotient = dividend / d;
1499 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1500 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1501
1502 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001503 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001504
1505 return (mbedtls_mpi_uint) quotient;
1506#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001507
1508 /*
1509 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1510 * Vol. 2 - Seminumerical Algorithms, Knuth
1511 */
1512
1513 /*
1514 * Normalize the divisor, d, and dividend, u0, u1
1515 */
1516 s = mbedtls_clz( d );
1517 d = d << s;
1518
1519 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001520 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001521 u0 = u0 << s;
1522
1523 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001524 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001525
1526 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001527 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001528
1529 /*
1530 * Find the first quotient and remainder
1531 */
1532 q1 = u1 / d1;
1533 r0 = u1 - d1 * q1;
1534
1535 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1536 {
1537 q1 -= 1;
1538 r0 += d1;
1539
1540 if ( r0 >= radix ) break;
1541 }
1542
Simon Butcherf5ba0452015-12-27 23:01:55 +00001543 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001544 q0 = rAX / d1;
1545 r0 = rAX - q0 * d1;
1546
1547 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1548 {
1549 q0 -= 1;
1550 r0 += d1;
1551
1552 if ( r0 >= radix ) break;
1553 }
1554
1555 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001556 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001557
1558 quotient = q1 * radix + q0;
1559
1560 return quotient;
1561#endif
1562}
1563
1564/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001565 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001566 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001567int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1568 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001569{
Paul Bakker23986e52011-04-24 08:57:21 +00001570 int ret;
1571 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001572 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001573 MPI_VALIDATE_RET( A != NULL );
1574 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001576 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1577 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001578
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001579 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1580 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001581
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001582 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001583 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001584 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1585 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001586 return( 0 );
1587 }
1588
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001589 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1590 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001591 X.s = Y.s = 1;
1592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001593 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1594 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1595 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1596 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001597
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001598 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001599 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001600 {
1601 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001602 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1603 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001604 }
1605 else k = 0;
1606
1607 n = X.n - 1;
1608 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001609 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001610
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001611 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001612 {
1613 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001614 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001615 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001616 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001617
1618 for( i = n; i > t ; i-- )
1619 {
1620 if( X.p[i] >= Y.p[t] )
1621 Z.p[i - t - 1] = ~0;
1622 else
1623 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001624 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1625 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001626 }
1627
1628 Z.p[i - t - 1]++;
1629 do
1630 {
1631 Z.p[i - t - 1]--;
1632
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001633 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001634 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001635 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001637
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001638 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001639 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1640 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001641 T2.p[2] = X.p[i];
1642 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001643 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001644
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001645 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1646 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1647 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001648
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001649 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001650 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1652 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1653 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001654 Z.p[i - t - 1]--;
1655 }
1656 }
1657
1658 if( Q != NULL )
1659 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001660 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001661 Q->s = A->s * B->s;
1662 }
1663
1664 if( R != NULL )
1665 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001666 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001667 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001668 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001669
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001670 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001671 R->s = 1;
1672 }
1673
1674cleanup:
1675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001676 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1677 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001678
1679 return( ret );
1680}
1681
1682/*
1683 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001684 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001685int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1686 const mbedtls_mpi *A,
1687 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001688{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001689 mbedtls_mpi _B;
1690 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001691 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001692
1693 p[0] = ( b < 0 ) ? -b : b;
1694 _B.s = ( b < 0 ) ? -1 : 1;
1695 _B.n = 1;
1696 _B.p = p;
1697
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001698 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001699}
1700
1701/*
1702 * Modulo: R = A mod B
1703 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001704int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001705{
1706 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001707 MPI_VALIDATE_RET( R != NULL );
1708 MPI_VALIDATE_RET( A != NULL );
1709 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001710
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001711 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1712 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001713
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001714 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001715
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001716 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1717 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001718
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001719 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1720 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001721
1722cleanup:
1723
1724 return( ret );
1725}
1726
1727/*
1728 * Modulo: r = A mod b
1729 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001730int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001731{
Paul Bakker23986e52011-04-24 08:57:21 +00001732 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001733 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001734 MPI_VALIDATE_RET( r != NULL );
1735 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001736
1737 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001738 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001739
1740 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001741 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001742
1743 /*
1744 * handle trivial cases
1745 */
1746 if( b == 1 )
1747 {
1748 *r = 0;
1749 return( 0 );
1750 }
1751
1752 if( b == 2 )
1753 {
1754 *r = A->p[0] & 1;
1755 return( 0 );
1756 }
1757
1758 /*
1759 * general case
1760 */
Paul Bakker23986e52011-04-24 08:57:21 +00001761 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001762 {
Paul Bakker23986e52011-04-24 08:57:21 +00001763 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001764 y = ( y << biH ) | ( x >> biH );
1765 z = y / b;
1766 y -= z * b;
1767
1768 x <<= biH;
1769 y = ( y << biH ) | ( x >> biH );
1770 z = y / b;
1771 y -= z * b;
1772 }
1773
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001774 /*
1775 * If A is negative, then the current y represents a negative value.
1776 * Flipping it to the positive side.
1777 */
1778 if( A->s < 0 && y != 0 )
1779 y = b - y;
1780
Paul Bakker5121ce52009-01-03 21:22:43 +00001781 *r = y;
1782
1783 return( 0 );
1784}
1785
1786/*
1787 * Fast Montgomery initialization (thanks to Tom St Denis)
1788 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001789static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001790{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001791 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001792 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001793
1794 x = m0;
1795 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001796
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001797 for( i = biL; i >= 8; i /= 2 )
1798 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001799
1800 *mm = ~x + 1;
1801}
1802
1803/*
1804 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1805 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001806static 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 +02001807 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001808{
Paul Bakker23986e52011-04-24 08:57:21 +00001809 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001810 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001811
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001812 if( T->n < N->n + 1 || T->p == NULL )
1813 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1814
Paul Bakker5121ce52009-01-03 21:22:43 +00001815 memset( T->p, 0, T->n * ciL );
1816
1817 d = T->p;
1818 n = N->n;
1819 m = ( B->n < n ) ? B->n : n;
1820
1821 for( i = 0; i < n; i++ )
1822 {
1823 /*
1824 * T = (T + u0*B + u1*N) / 2^biL
1825 */
1826 u0 = A->p[i];
1827 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1828
1829 mpi_mul_hlp( m, B->p, d, u0 );
1830 mpi_mul_hlp( n, N->p, d, u1 );
1831
1832 *d++ = u0; d[n + 1] = 0;
1833 }
1834
Paul Bakker66d5d072014-06-17 16:39:18 +02001835 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001836
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001837 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001838 mpi_sub_hlp( n, N->p, A->p );
1839 else
1840 /* prevent timing attacks */
1841 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001842
1843 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001844}
1845
1846/*
1847 * Montgomery reduction: A = A * R^-1 mod N
1848 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001849static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1850 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001851{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001852 mbedtls_mpi_uint z = 1;
1853 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001854
Paul Bakker8ddb6452013-02-27 14:56:33 +01001855 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001856 U.p = &z;
1857
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001858 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001859}
1860
1861/*
1862 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1863 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001864int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1865 const mbedtls_mpi *E, const mbedtls_mpi *N,
1866 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001867{
Paul Bakker23986e52011-04-24 08:57:21 +00001868 int ret;
1869 size_t wbits, wsize, one = 1;
1870 size_t i, j, nblimbs;
1871 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001872 mbedtls_mpi_uint ei, mm, state;
1873 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001874 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001875
Hanno Becker73d7d792018-12-11 10:35:51 +00001876 MPI_VALIDATE_RET( X != NULL );
1877 MPI_VALIDATE_RET( A != NULL );
1878 MPI_VALIDATE_RET( E != NULL );
1879 MPI_VALIDATE_RET( N != NULL );
1880
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001881 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001883
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001884 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1885 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001886
1887 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001888 * Init temps and window size
1889 */
1890 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001891 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1892 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001893 memset( W, 0, sizeof( W ) );
1894
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001895 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001896
1897 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1898 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1899
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001900 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1901 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001902
Paul Bakker5121ce52009-01-03 21:22:43 +00001903 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001904 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1905 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1906 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001907
1908 /*
Paul Bakker50546922012-05-19 08:40:49 +00001909 * Compensate for negative A (and correct at the end)
1910 */
1911 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001912 if( neg )
1913 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001914 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001915 Apos.s = 1;
1916 A = &Apos;
1917 }
1918
1919 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001920 * If 1st call, pre-compute R^2 mod N
1921 */
1922 if( _RR == NULL || _RR->p == NULL )
1923 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001924 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1925 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1926 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001927
1928 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001930 }
1931 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001932 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001933
1934 /*
1935 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1936 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001937 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1938 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001939 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001940 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001941
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001942 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001943
1944 /*
1945 * X = R^2 * R^-1 mod N = R mod N
1946 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001947 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001948 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001949
1950 if( wsize > 1 )
1951 {
1952 /*
1953 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1954 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001955 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001957 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1958 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001959
1960 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001961 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001962
Paul Bakker5121ce52009-01-03 21:22:43 +00001963 /*
1964 * W[i] = W[i - 1] * W[1]
1965 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001966 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001967 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001968 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1969 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001970
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001971 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001972 }
1973 }
1974
1975 nblimbs = E->n;
1976 bufsize = 0;
1977 nbits = 0;
1978 wbits = 0;
1979 state = 0;
1980
1981 while( 1 )
1982 {
1983 if( bufsize == 0 )
1984 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001985 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001986 break;
1987
Paul Bakker0d7702c2013-10-29 16:18:35 +01001988 nblimbs--;
1989
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001990 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001991 }
1992
1993 bufsize--;
1994
1995 ei = (E->p[nblimbs] >> bufsize) & 1;
1996
1997 /*
1998 * skip leading 0s
1999 */
2000 if( ei == 0 && state == 0 )
2001 continue;
2002
2003 if( ei == 0 && state == 1 )
2004 {
2005 /*
2006 * out of window, square X
2007 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002008 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002009 continue;
2010 }
2011
2012 /*
2013 * add ei to current window
2014 */
2015 state = 2;
2016
2017 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002018 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002019
2020 if( nbits == wsize )
2021 {
2022 /*
2023 * X = X^wsize R^-1 mod N
2024 */
2025 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002026 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002027
2028 /*
2029 * X = X * W[wbits] R^-1 mod N
2030 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002031 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002032
2033 state--;
2034 nbits = 0;
2035 wbits = 0;
2036 }
2037 }
2038
2039 /*
2040 * process the remaining bits
2041 */
2042 for( i = 0; i < nbits; i++ )
2043 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002044 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002045
2046 wbits <<= 1;
2047
Paul Bakker66d5d072014-06-17 16:39:18 +02002048 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002049 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002050 }
2051
2052 /*
2053 * X = A^E * R * R^-1 mod N = A^E mod N
2054 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002055 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002056
Hanno Beckera4af1c42017-04-18 09:07:45 +01002057 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002058 {
2059 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002061 }
2062
Paul Bakker5121ce52009-01-03 21:22:43 +00002063cleanup:
2064
Paul Bakker66d5d072014-06-17 16:39:18 +02002065 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002066 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002067
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002068 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002069
Paul Bakker75a28602014-03-31 12:08:17 +02002070 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002071 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002072
2073 return( ret );
2074}
2075
Paul Bakker5121ce52009-01-03 21:22:43 +00002076/*
2077 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2078 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002079int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002080{
Paul Bakker23986e52011-04-24 08:57:21 +00002081 int ret;
2082 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002083 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002084
Hanno Becker73d7d792018-12-11 10:35:51 +00002085 MPI_VALIDATE_RET( G != NULL );
2086 MPI_VALIDATE_RET( A != NULL );
2087 MPI_VALIDATE_RET( B != NULL );
2088
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002089 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002090
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002091 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2092 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002093
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002094 lz = mbedtls_mpi_lsb( &TA );
2095 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002096
Paul Bakker66d5d072014-06-17 16:39:18 +02002097 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002098 lz = lzt;
2099
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002100 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2101 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002102
Paul Bakker5121ce52009-01-03 21:22:43 +00002103 TA.s = TB.s = 1;
2104
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002105 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002106 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002107 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2108 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002110 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002111 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002112 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2113 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002114 }
2115 else
2116 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002117 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2118 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002119 }
2120 }
2121
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002122 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2123 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002124
2125cleanup:
2126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002127 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002128
2129 return( ret );
2130}
2131
Paul Bakker33dc46b2014-04-30 16:11:39 +02002132/*
2133 * Fill X with size bytes of random.
2134 *
2135 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002136 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002137 * deterministic, eg for tests).
2138 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002139int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002140 int (*f_rng)(void *, unsigned char *, size_t),
2141 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002142{
Paul Bakker23986e52011-04-24 08:57:21 +00002143 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002144 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002145 size_t const overhead = ( limbs * ciL ) - size;
2146 unsigned char *Xp;
2147
Hanno Becker8ce11a32018-12-19 16:18:52 +00002148 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002149 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002150
Hanno Beckerda1655a2017-10-18 14:21:44 +01002151 /* Ensure that target MPI has exactly the necessary number of limbs */
2152 if( X->n != limbs )
2153 {
2154 mbedtls_mpi_free( X );
2155 mbedtls_mpi_init( X );
2156 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2157 }
2158 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002159
Hanno Beckerda1655a2017-10-18 14:21:44 +01002160 Xp = (unsigned char*) X->p;
2161 f_rng( p_rng, Xp + overhead, size );
2162
Hanno Becker2be8a552018-10-25 12:40:09 +01002163 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002164
2165cleanup:
2166 return( ret );
2167}
2168
Paul Bakker5121ce52009-01-03 21:22:43 +00002169/*
2170 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2171 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002172int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002173{
2174 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002175 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002176 MPI_VALIDATE_RET( X != NULL );
2177 MPI_VALIDATE_RET( A != NULL );
2178 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002179
Hanno Becker4bcb4912017-04-18 15:49:39 +01002180 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002181 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002182
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002183 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2184 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2185 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002186
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002187 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002189 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002190 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002191 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002192 goto cleanup;
2193 }
2194
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002195 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2196 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2197 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2198 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002199
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002200 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2201 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2202 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2203 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002204
2205 do
2206 {
2207 while( ( TU.p[0] & 1 ) == 0 )
2208 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002209 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002210
2211 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2212 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002213 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2214 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002215 }
2216
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002217 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2218 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002219 }
2220
2221 while( ( TV.p[0] & 1 ) == 0 )
2222 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002223 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002224
2225 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2226 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002227 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2228 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002229 }
2230
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002231 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2232 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002233 }
2234
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002235 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002236 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002237 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2238 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2239 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002240 }
2241 else
2242 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002243 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2244 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2245 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002246 }
2247 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002248 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002249
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002250 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2251 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002252
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002253 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2254 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002255
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002256 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002257
2258cleanup:
2259
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002260 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2261 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2262 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002263
2264 return( ret );
2265}
2266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002267#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002268
Paul Bakker5121ce52009-01-03 21:22:43 +00002269static const int small_prime[] =
2270{
2271 3, 5, 7, 11, 13, 17, 19, 23,
2272 29, 31, 37, 41, 43, 47, 53, 59,
2273 61, 67, 71, 73, 79, 83, 89, 97,
2274 101, 103, 107, 109, 113, 127, 131, 137,
2275 139, 149, 151, 157, 163, 167, 173, 179,
2276 181, 191, 193, 197, 199, 211, 223, 227,
2277 229, 233, 239, 241, 251, 257, 263, 269,
2278 271, 277, 281, 283, 293, 307, 311, 313,
2279 317, 331, 337, 347, 349, 353, 359, 367,
2280 373, 379, 383, 389, 397, 401, 409, 419,
2281 421, 431, 433, 439, 443, 449, 457, 461,
2282 463, 467, 479, 487, 491, 499, 503, 509,
2283 521, 523, 541, 547, 557, 563, 569, 571,
2284 577, 587, 593, 599, 601, 607, 613, 617,
2285 619, 631, 641, 643, 647, 653, 659, 661,
2286 673, 677, 683, 691, 701, 709, 719, 727,
2287 733, 739, 743, 751, 757, 761, 769, 773,
2288 787, 797, 809, 811, 821, 823, 827, 829,
2289 839, 853, 857, 859, 863, 877, 881, 883,
2290 887, 907, 911, 919, 929, 937, 941, 947,
2291 953, 967, 971, 977, 983, 991, 997, -103
2292};
2293
2294/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002295 * Small divisors test (X must be positive)
2296 *
2297 * Return values:
2298 * 0: no small factor (possible prime, more tests needed)
2299 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002300 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002301 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002302 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002303static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002304{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002305 int ret = 0;
2306 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002308
Paul Bakker5121ce52009-01-03 21:22:43 +00002309 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002310 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002311
2312 for( i = 0; small_prime[i] > 0; i++ )
2313 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002314 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002315 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002316
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002317 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002318
2319 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002320 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002321 }
2322
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002323cleanup:
2324 return( ret );
2325}
2326
2327/*
2328 * Miller-Rabin pseudo-primality test (HAC 4.24)
2329 */
Janos Follathda31fa12018-09-03 14:45:23 +01002330static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002331 int (*f_rng)(void *, unsigned char *, size_t),
2332 void *p_rng )
2333{
Pascal Junodb99183d2015-03-11 16:49:45 +01002334 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002335 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002336 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002337
Hanno Becker8ce11a32018-12-19 16:18:52 +00002338 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002339 MPI_VALIDATE_RET( f_rng != NULL );
2340
2341 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2342 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002343 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002344
Paul Bakker5121ce52009-01-03 21:22:43 +00002345 /*
2346 * W = |X| - 1
2347 * R = W >> lsb( W )
2348 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002349 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2350 s = mbedtls_mpi_lsb( &W );
2351 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2352 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002353
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002354 i = mbedtls_mpi_bitlen( X );
Janos Follathf301d232018-08-14 13:34:01 +01002355
Janos Follathda31fa12018-09-03 14:45:23 +01002356 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002357 {
2358 /*
2359 * pick a random A, 1 < A < |X| - 1
2360 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002361 count = 0;
2362 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002363 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002364
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002365 j = mbedtls_mpi_bitlen( &A );
2366 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002367 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002368 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002369 }
2370
2371 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002372 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002373 }
2374
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002375 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2376 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002377
2378 /*
2379 * A = A^R mod |X|
2380 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002381 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2384 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002385 continue;
2386
2387 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002388 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002389 {
2390 /*
2391 * A = A * A mod |X|
2392 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002393 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2394 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002397 break;
2398
2399 j++;
2400 }
2401
2402 /*
2403 * not prime if A != |X| - 1 or A == 1
2404 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002405 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2406 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002407 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002408 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002409 break;
2410 }
2411 }
2412
2413cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002414 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2415 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002416 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002417
2418 return( ret );
2419}
2420
2421/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002422 * Pseudo-primality test: small factors, then Miller-Rabin
2423 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002424int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2425 int (*f_rng)(void *, unsigned char *, size_t),
2426 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002427{
2428 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002429 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002430 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002431 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002432
2433 XX.s = 1;
2434 XX.n = X->n;
2435 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002436
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002437 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2438 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2439 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002440
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002441 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002442 return( 0 );
2443
2444 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2445 {
2446 if( ret == 1 )
2447 return( 0 );
2448
2449 return( ret );
2450 }
2451
Janos Follathda31fa12018-09-03 14:45:23 +01002452 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002453}
2454
Janos Follatha0b67c22018-09-18 14:48:23 +01002455#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002456/*
2457 * Pseudo-primality test, error probability 2^-80
2458 */
2459int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2460 int (*f_rng)(void *, unsigned char *, size_t),
2461 void *p_rng )
2462{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002463 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002464 MPI_VALIDATE_RET( f_rng != NULL );
2465
Janos Follatha0b67c22018-09-18 14:48:23 +01002466 /*
2467 * In the past our key generation aimed for an error rate of at most
2468 * 2^-80. Since this function is deprecated, aim for the same certainty
2469 * here as well.
2470 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002471 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002472}
Janos Follatha0b67c22018-09-18 14:48:23 +01002473#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002474
2475/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002476 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002477 *
Janos Follathf301d232018-08-14 13:34:01 +01002478 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2479 * be either 1024 bits or 1536 bits long, and flags must contain
2480 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002481 */
Janos Follath7c025a92018-08-14 11:08:41 +01002482int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002483 int (*f_rng)(void *, unsigned char *, size_t),
2484 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002485{
Jethro Beekman66689272018-02-14 19:24:10 -08002486#ifdef MBEDTLS_HAVE_INT64
2487// ceil(2^63.5)
2488#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2489#else
2490// ceil(2^31.5)
2491#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2492#endif
2493 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002494 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002495 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002496 mbedtls_mpi_uint r;
2497 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002498
Hanno Becker8ce11a32018-12-19 16:18:52 +00002499 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002500 MPI_VALIDATE_RET( f_rng != NULL );
2501
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002502 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2503 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002504
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002505 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002506
2507 n = BITS_TO_LIMBS( nbits );
2508
Janos Follathda31fa12018-09-03 14:45:23 +01002509 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2510 {
2511 /*
2512 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2513 */
2514 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2515 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2516 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2517 }
2518 else
2519 {
2520 /*
2521 * 2^-100 error probability, number of rounds computed based on HAC,
2522 * fact 4.48
2523 */
2524 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2525 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2526 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2527 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2528 }
2529
Jethro Beekman66689272018-02-14 19:24:10 -08002530 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002531 {
Jethro Beekman66689272018-02-14 19:24:10 -08002532 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2533 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2534 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2535
2536 k = n * biL;
2537 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2538 X->p[0] |= 1;
2539
Janos Follath7c025a92018-08-14 11:08:41 +01002540 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002541 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002542 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002543
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002544 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002545 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002546 }
Jethro Beekman66689272018-02-14 19:24:10 -08002547 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002548 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002549 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002550 * An necessary condition for Y and X = 2Y + 1 to be prime
2551 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2552 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002553 */
Jethro Beekman66689272018-02-14 19:24:10 -08002554
2555 X->p[0] |= 2;
2556
2557 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2558 if( r == 0 )
2559 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2560 else if( r == 1 )
2561 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2562
2563 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2564 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2565 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2566
2567 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002568 {
Jethro Beekman66689272018-02-14 19:24:10 -08002569 /*
2570 * First, check small factors for X and Y
2571 * before doing Miller-Rabin on any of them
2572 */
2573 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2574 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002575 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002576 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002577 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002578 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002579 goto cleanup;
2580
2581 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2582 goto cleanup;
2583
2584 /*
2585 * Next candidates. We want to preserve Y = (X-1) / 2 and
2586 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2587 * so up Y by 6 and X by 12.
2588 */
2589 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2590 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002591 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002592 }
2593 }
2594
2595cleanup:
2596
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002597 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002598
2599 return( ret );
2600}
2601
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002602#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002603
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002604#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002605
Paul Bakker23986e52011-04-24 08:57:21 +00002606#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002607
2608static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2609{
2610 { 693, 609, 21 },
2611 { 1764, 868, 28 },
2612 { 768454923, 542167814, 1 }
2613};
2614
Paul Bakker5121ce52009-01-03 21:22:43 +00002615/*
2616 * Checkup routine
2617 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002618int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002619{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002620 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002621 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002622
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002623 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2624 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002625
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002626 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002627 "EFE021C2645FD1DC586E69184AF4A31E" \
2628 "D5F53E93B5F123FA41680867BA110131" \
2629 "944FE7952E2517337780CB0DB80E61AA" \
2630 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2631
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002632 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002633 "B2E7EFD37075B9F03FF989C7C5051C20" \
2634 "34D2A323810251127E7BF8625A4F49A5" \
2635 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2636 "5B5C25763222FEFCCFC38B832366C29E" ) );
2637
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002638 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002639 "0066A198186C18C10B2F5ED9B522752A" \
2640 "9830B69916E535C8F047518A889A43A5" \
2641 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2642
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002643 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002644
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002645 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002646 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2647 "9E857EA95A03512E2BAE7391688D264A" \
2648 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2649 "8001B72E848A38CAE1C65F78E56ABDEF" \
2650 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2651 "ECF677152EF804370C1A305CAF3B5BF1" \
2652 "30879B56C61DE584A0F53A2447A51E" ) );
2653
2654 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002655 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002656
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002657 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002658 {
2659 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002660 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002661
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002662 ret = 1;
2663 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002664 }
2665
2666 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002667 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002669 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002670
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002671 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002672 "256567336059E52CAE22925474705F39A94" ) );
2673
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002674 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002675 "6613F26162223DF488E9CD48CC132C7A" \
2676 "0AC93C701B001B092E4E5B9F73BCD27B" \
2677 "9EE50D0657C77F374E903CDFA4C642" ) );
2678
2679 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002680 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002682 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2683 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002684 {
2685 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002686 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002687
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002688 ret = 1;
2689 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002690 }
2691
2692 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002693 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002694
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002695 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002697 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002698 "36E139AEA55215609D2816998ED020BB" \
2699 "BD96C37890F65171D948E9BC7CBAA4D9" \
2700 "325D24D6A3C12710F10A09FA08AB87" ) );
2701
2702 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002703 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002704
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002705 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002706 {
2707 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002708 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002709
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002710 ret = 1;
2711 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002712 }
2713
2714 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002715 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002716
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002717 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002718
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002719 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002720 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2721 "C3DBA76456363A10869622EAC2DD84EC" \
2722 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2723
2724 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002725 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002726
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002727 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002728 {
2729 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002730 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002731
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002732 ret = 1;
2733 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002734 }
2735
2736 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002737 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002738
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002739 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002740 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002741
Paul Bakker66d5d072014-06-17 16:39:18 +02002742 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002743 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002744 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2745 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002746
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002747 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002748
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002749 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002750 {
2751 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002752 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002753
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002754 ret = 1;
2755 goto cleanup;
2756 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002757 }
2758
2759 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002760 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002761
Paul Bakker5121ce52009-01-03 21:22:43 +00002762cleanup:
2763
2764 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002765 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002766
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002767 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2768 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002769
2770 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002771 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002772
2773 return( ret );
2774}
2775
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002776#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002777
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002778#endif /* MBEDTLS_BIGNUM_C */