blob: 592aa2e819b6feabc225218e7d9890d771fd2a74 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050048#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000049
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <string.h>
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020054#else
Rich Evans00ab4702015-02-06 13:43:58 +000055#include <stdio.h>
56#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020058#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020060#endif
61
Hanno Becker73d7d792018-12-11 10:35:51 +000062#define MPI_VALIDATE_RET( cond ) \
63 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
64#define MPI_VALIDATE( cond ) \
65 MBEDTLS_INTERNAL_VALIDATE( cond )
66
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020067#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000068#define biL (ciL << 3) /* bits in limb */
69#define biH (ciL << 2) /* half limb size */
70
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010071#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
72
Paul Bakker5121ce52009-01-03 21:22:43 +000073/*
74 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020075 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000076 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020077#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
78#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000079
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050080/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050081static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
82{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050083 mbedtls_platform_zeroize( v, ciL * n );
84}
85
Paul Bakker5121ce52009-01-03 21:22:43 +000086/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000088 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000090{
Hanno Becker73d7d792018-12-11 10:35:51 +000091 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000092
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 X->s = 1;
94 X->n = 0;
95 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000096}
97
98/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000099 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000103 if( X == NULL )
104 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000105
Paul Bakker6c591fa2011-05-05 11:49:20 +0000106 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000107 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200108 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000110 }
111
Paul Bakker6c591fa2011-05-05 11:49:20 +0000112 X->s = 1;
113 X->n = 0;
114 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000115}
116
117/*
118 * Enlarge to the specified number of limbs
119 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000121{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000123 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200126 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000127
Paul Bakker5121ce52009-01-03 21:22:43 +0000128 if( X->n < nblimbs )
129 {
Simon Butcher29176892016-05-20 00:19:09 +0100130 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200131 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000132
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 if( X->p != NULL )
134 {
135 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200136 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000138 }
139
140 X->n = nblimbs;
141 X->p = p;
142 }
143
144 return( 0 );
145}
146
147/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100148 * Resize down as much as possible,
149 * while keeping at least the specified number of limbs
150 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000155 MPI_VALIDATE_RET( X != NULL );
156
157 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
158 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100159
160 /* Actually resize up in this case */
161 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163
164 for( i = X->n - 1; i > 0; i-- )
165 if( X->p[i] != 0 )
166 break;
167 i++;
168
169 if( i < nblimbs )
170 i = nblimbs;
171
Simon Butcher29176892016-05-20 00:19:09 +0100172 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200173 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100174
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175 if( X->p != NULL )
176 {
177 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200178 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100180 }
181
182 X->n = i;
183 X->p = p;
184
185 return( 0 );
186}
187
188/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000189 * Copy the contents of Y into X
190 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000192{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100193 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000194 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000195 MPI_VALIDATE_RET( X != NULL );
196 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000197
198 if( X == Y )
199 return( 0 );
200
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200201 if( Y->p == NULL )
202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200204 return( 0 );
205 }
206
Paul Bakker5121ce52009-01-03 21:22:43 +0000207 for( i = Y->n - 1; i > 0; i-- )
208 if( Y->p[i] != 0 )
209 break;
210 i++;
211
212 X->s = Y->s;
213
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100214 if( X->n < i )
215 {
216 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
217 }
218 else
219 {
220 memset( X->p + i, 0, ( X->n - i ) * ciL );
221 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
Paul Bakker5121ce52009-01-03 21:22:43 +0000223 memcpy( X->p, Y->p, i * ciL );
224
225cleanup:
226
227 return( ret );
228}
229
230/*
231 * Swap the contents of X and Y
232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000234{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000236 MPI_VALIDATE( X != NULL );
237 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 memcpy( &T, X, sizeof( mbedtls_mpi ) );
240 memcpy( X, Y, sizeof( mbedtls_mpi ) );
241 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000242}
243
244/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100245 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100246 * about whether the assignment was made or not.
247 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100248 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250{
251 int ret = 0;
252 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000253 MPI_VALIDATE_RET( X != NULL );
254 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100255
Pascal Junodb99183d2015-03-11 16:49:45 +0100256 /* make sure assign is 0 or 1 in a time-constant manner */
257 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100260
Paul Bakker66d5d072014-06-17 16:39:18 +0200261 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100262
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100263 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200264 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100265
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100266 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200267 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100268
269cleanup:
270 return( ret );
271}
272
273/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274 * Conditionally swap X and Y, without leaking information
275 * about whether the swap was made or not.
276 * Here it is not ok to simply swap the pointers, which whould lead to
277 * different memory access patterns when X and Y are used afterwards.
278 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100280{
281 int ret, s;
282 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000284 MPI_VALIDATE_RET( X != NULL );
285 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286
287 if( X == Y )
288 return( 0 );
289
Pascal Junodb99183d2015-03-11 16:49:45 +0100290 /* make sure swap is 0 or 1 in a time-constant manner */
291 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100295
296 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200297 X->s = X->s * ( 1 - swap ) + Y->s * swap;
298 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100299
300
301 for( i = 0; i < X->n; i++ )
302 {
303 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200304 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
305 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100306 }
307
308cleanup:
309 return( ret );
310}
311
312/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000313 * Set value from integer
314 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000316{
317 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +0000318 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200320 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000321 memset( X->p, 0, X->n * ciL );
322
323 X->p[0] = ( z < 0 ) ? -z : z;
324 X->s = ( z < 0 ) ? -1 : 1;
325
326cleanup:
327
328 return( ret );
329}
330
331/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332 * Get a specific bit
333 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000335{
Hanno Becker73d7d792018-12-11 10:35:51 +0000336 MPI_VALIDATE_RET( X != NULL );
337
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338 if( X->n * biL <= pos )
339 return( 0 );
340
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200341 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000342}
343
Gilles Peskine11cdb052018-11-20 16:47:47 +0100344/* Get a specific byte, without range checks. */
345#define GET_BYTE( X, i ) \
346 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
347
Paul Bakker2f5947e2011-05-18 15:47:11 +0000348/*
349 * Set a bit to a specific value of 0 or 1
350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000352{
353 int ret = 0;
354 size_t off = pos / biL;
355 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000356 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000357
358 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200360
Paul Bakker2f5947e2011-05-18 15:47:11 +0000361 if( X->n * biL <= pos )
362 {
363 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200364 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000367 }
368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
370 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000371
372cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200373
Paul Bakker2f5947e2011-05-18 15:47:11 +0000374 return( ret );
375}
376
377/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200378 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000381{
Paul Bakker23986e52011-04-24 08:57:21 +0000382 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000383 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000384
385 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000386 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
388 return( count );
389
390 return( 0 );
391}
392
393/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000394 * Count leading zero bits in a given integer
395 */
396static size_t mbedtls_clz( const mbedtls_mpi_uint x )
397{
398 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100399 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000400
401 for( j = 0; j < biL; j++ )
402 {
403 if( x & mask ) break;
404
405 mask >>= 1;
406 }
407
408 return j;
409}
410
411/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200412 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000413 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200414size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000415{
Paul Bakker23986e52011-04-24 08:57:21 +0000416 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200418 if( X->n == 0 )
419 return( 0 );
420
Paul Bakker5121ce52009-01-03 21:22:43 +0000421 for( i = X->n - 1; i > 0; i-- )
422 if( X->p[i] != 0 )
423 break;
424
Simon Butcher15b15d12015-11-26 19:35:03 +0000425 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
Paul Bakker23986e52011-04-24 08:57:21 +0000427 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000428}
429
430/*
431 * Return the total size in bytes
432 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000434{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200435 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000436}
437
438/*
439 * Convert an ASCII character to digit value
440 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000442{
443 *d = 255;
444
445 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
446 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
447 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 if( *d >= (mbedtls_mpi_uint) radix )
450 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000451
452 return( 0 );
453}
454
455/*
456 * Import from an ASCII string
457 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000459{
Paul Bakker23986e52011-04-24 08:57:21 +0000460 int ret;
461 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 mbedtls_mpi_uint d;
463 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000464 MPI_VALIDATE_RET( X != NULL );
465 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000466
467 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000468 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000471
Paul Bakkerff60ee62010-03-16 21:09:09 +0000472 slen = strlen( s );
473
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 if( radix == 16 )
475 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100476 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200477 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
478
Paul Bakkerff60ee62010-03-16 21:09:09 +0000479 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
482 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
Paul Bakker23986e52011-04-24 08:57:21 +0000484 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000485 {
Paul Bakker23986e52011-04-24 08:57:21 +0000486 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000487 {
488 X->s = -1;
489 break;
490 }
491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200493 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494 }
495 }
496 else
497 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
Paul Bakkerff60ee62010-03-16 21:09:09 +0000500 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000501 {
502 if( i == 0 && s[i] == '-' )
503 {
504 X->s = -1;
505 continue;
506 }
507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
509 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000510
511 if( X->s == 1 )
512 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000514 }
515 else
516 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000518 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000519 }
520 }
521
522cleanup:
523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000525
526 return( ret );
527}
528
529/*
Ron Eldora16fa292018-11-20 14:07:01 +0200530 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000531 */
Ron Eldora16fa292018-11-20 14:07:01 +0200532static int mpi_write_hlp( mbedtls_mpi *X, int radix,
533 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000534{
535 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200537 size_t length = 0;
538 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
Ron Eldora16fa292018-11-20 14:07:01 +0200540 do
541 {
542 if( length >= buflen )
543 {
544 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
545 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000546
Ron Eldora16fa292018-11-20 14:07:01 +0200547 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
548 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
549 /*
550 * Write the residue in the current position, as an ASCII character.
551 */
552 if( r < 0xA )
553 *(--p_end) = (char)( '0' + r );
554 else
555 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000556
Ron Eldora16fa292018-11-20 14:07:01 +0200557 length++;
558 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000559
Ron Eldora16fa292018-11-20 14:07:01 +0200560 memmove( *p, p_end, length );
561 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000562
563cleanup:
564
565 return( ret );
566}
567
568/*
569 * Export into an ASCII string
570 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100571int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
572 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000573{
Paul Bakker23986e52011-04-24 08:57:21 +0000574 int ret = 0;
575 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000576 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000578 MPI_VALIDATE_RET( X != NULL );
579 MPI_VALIDATE_RET( olen != NULL );
580 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000581
582 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000583 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200585 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000586 if( radix >= 4 ) n >>= 1;
587 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000588 /*
589 * Round up the buffer length to an even value to ensure that there is
590 * enough room for hexadecimal values that can be represented in an odd
591 * number of digits.
592 */
593 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000594
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100595 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000596 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100597 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000599 }
600
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100601 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000603
604 if( X->s == -1 )
605 *p++ = '-';
606
607 if( radix == 16 )
608 {
Paul Bakker23986e52011-04-24 08:57:21 +0000609 int c;
610 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000611
Paul Bakker23986e52011-04-24 08:57:21 +0000612 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000613 {
Paul Bakker23986e52011-04-24 08:57:21 +0000614 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000615 {
Paul Bakker23986e52011-04-24 08:57:21 +0000616 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000617
Paul Bakker6c343d72014-07-10 14:36:19 +0200618 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000619 continue;
620
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000621 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000622 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 k = 1;
624 }
625 }
626 }
627 else
628 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000630
631 if( T.s == -1 )
632 T.s = 1;
633
Ron Eldora16fa292018-11-20 14:07:01 +0200634 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000635 }
636
637 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100638 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000639
640cleanup:
641
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000643
644 return( ret );
645}
646
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200647#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000648/*
649 * Read X from an opened file
650 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000652{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000654 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000655 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000656 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000657 * Buffer should have space for (short) label and decimal formatted MPI,
658 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000659 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200660 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000661
Hanno Becker73d7d792018-12-11 10:35:51 +0000662 MPI_VALIDATE_RET( X != NULL );
663 MPI_VALIDATE_RET( fin != NULL );
664
665 if( radix < 2 || radix > 16 )
666 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
667
Paul Bakker5121ce52009-01-03 21:22:43 +0000668 memset( s, 0, sizeof( s ) );
669 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000671
672 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000673 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000675
Hanno Beckerb2034b72017-04-26 11:46:46 +0100676 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
677 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000678
679 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100680 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000681 if( mpi_get_digit( &d, radix, *p ) != 0 )
682 break;
683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000685}
686
687/*
688 * Write X into an opened file (or stdout if fout == NULL)
689 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000691{
Paul Bakker23986e52011-04-24 08:57:21 +0000692 int ret;
693 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000694 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000695 * Buffer should have space for (short) label and decimal formatted MPI,
696 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000697 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000699 MPI_VALIDATE_RET( X != NULL );
700
701 if( radix < 2 || radix > 16 )
702 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000703
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100704 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000705
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100706 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
708 if( p == NULL ) p = "";
709
710 plen = strlen( p );
711 slen = strlen( s );
712 s[slen++] = '\r';
713 s[slen++] = '\n';
714
715 if( fout != NULL )
716 {
717 if( fwrite( p, 1, plen, fout ) != plen ||
718 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000720 }
721 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000723
724cleanup:
725
726 return( ret );
727}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000729
Hanno Beckerda1655a2017-10-18 14:21:44 +0100730
731/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
732 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000733
734static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
735{
736 uint8_t i;
737 mbedtls_mpi_uint tmp = 0;
738 /* This works regardless of the endianness. */
739 for( i = 0; i < ciL; i++, x >>= 8 )
740 tmp |= ( x & 0xFF ) << ( ( ciL - 1 - i ) << 3 );
741 return( tmp );
742}
743
744static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
745{
746#if defined(__BYTE_ORDER__)
747
748/* Nothing to do on bigendian systems. */
749#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
750 return( x );
751#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
752
753#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
754
755/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000756#if defined(__GNUC__) && defined(__GNUC_PREREQ)
757#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000758#define have_bswap
759#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000760#endif
761
762#if defined(__clang__) && defined(__has_builtin)
763#if __has_builtin(__builtin_bswap32) && \
764 __has_builtin(__builtin_bswap64)
765#define have_bswap
766#endif
767#endif
768
Hanno Beckerf8720072018-11-08 11:53:49 +0000769#if defined(have_bswap)
770 /* The compiler is hopefully able to statically evaluate this! */
771 switch( sizeof(mbedtls_mpi_uint) )
772 {
773 case 4:
774 return( __builtin_bswap32(x) );
775 case 8:
776 return( __builtin_bswap64(x) );
777 }
778#endif
779#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
780#endif /* __BYTE_ORDER__ */
781
782 /* Fall back to C-based reordering if we don't know the byte order
783 * or we couldn't use a compiler-specific builtin. */
784 return( mpi_uint_bigendian_to_host_c( x ) );
785}
786
Hanno Becker2be8a552018-10-25 12:40:09 +0100787static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100788{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100789 mbedtls_mpi_uint *cur_limb_left;
790 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100791 if( limbs == 0 )
792 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100793
794 /*
795 * Traverse limbs and
796 * - adapt byte-order in each limb
797 * - swap the limbs themselves.
798 * For that, simultaneously traverse the limbs from left to right
799 * and from right to left, as long as the left index is not bigger
800 * than the right index (it's not a problem if limbs is odd and the
801 * indices coincide in the last iteration).
802 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100803 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
804 cur_limb_left <= cur_limb_right;
805 cur_limb_left++, cur_limb_right-- )
806 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000807 mbedtls_mpi_uint tmp;
808 /* Note that if cur_limb_left == cur_limb_right,
809 * this code effectively swaps the bytes only once. */
810 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
811 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
812 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100813 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100814}
815
Paul Bakker5121ce52009-01-03 21:22:43 +0000816/*
Janos Follatha778a942019-02-13 10:28:28 +0000817 * Import X from unsigned binary data, little endian
818 */
819int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
820 const unsigned char *buf, size_t buflen )
821{
822 int ret;
823 size_t i;
824 size_t const limbs = CHARS_TO_LIMBS( buflen );
825
826 /* Ensure that target MPI has exactly the necessary number of limbs */
827 if( X->n != limbs )
828 {
829 mbedtls_mpi_free( X );
830 mbedtls_mpi_init( X );
831 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
832 }
833
834 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
835
836 for( i = 0; i < buflen; i++ )
837 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
838
839cleanup:
840
Janos Follath171a7ef2019-02-15 16:17:45 +0000841 /*
842 * This function is also used to import keys. However, wiping the buffers
843 * upon failure is not necessary because failure only can happen before any
844 * input is copied.
845 */
Janos Follatha778a942019-02-13 10:28:28 +0000846 return( ret );
847}
848
849/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000850 * Import X from unsigned binary data, big endian
851 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200852int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000853{
Paul Bakker23986e52011-04-24 08:57:21 +0000854 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100855 size_t const limbs = CHARS_TO_LIMBS( buflen );
856 size_t const overhead = ( limbs * ciL ) - buflen;
857 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000858
Hanno Becker8ce11a32018-12-19 16:18:52 +0000859 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000860 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
861
Hanno Becker073c1992017-10-17 15:17:27 +0100862 /* Ensure that target MPI has exactly the necessary number of limbs */
863 if( X->n != limbs )
864 {
865 mbedtls_mpi_free( X );
866 mbedtls_mpi_init( X );
867 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
868 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200869 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000870
Hanno Becker0e810b92019-01-03 17:13:11 +0000871 /* Avoid calling `memcpy` with NULL source argument,
872 * even if buflen is 0. */
873 if( buf != NULL )
874 {
875 Xp = (unsigned char*) X->p;
876 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100877
Hanno Becker0e810b92019-01-03 17:13:11 +0000878 mpi_bigendian_to_host( X->p, limbs );
879 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000880
881cleanup:
882
Janos Follath171a7ef2019-02-15 16:17:45 +0000883 /*
884 * This function is also used to import keys. However, wiping the buffers
885 * upon failure is not necessary because failure only can happen before any
886 * input is copied.
887 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000888 return( ret );
889}
890
891/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000892 * Export X into unsigned binary data, little endian
893 */
894int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
895 unsigned char *buf, size_t buflen )
896{
897 size_t stored_bytes = X->n * ciL;
898 size_t bytes_to_copy;
899 size_t i;
900
901 if( stored_bytes < buflen )
902 {
903 bytes_to_copy = stored_bytes;
904 }
905 else
906 {
907 bytes_to_copy = buflen;
908
909 /* The output buffer is smaller than the allocated size of X.
910 * However X may fit if its leading bytes are zero. */
911 for( i = bytes_to_copy; i < stored_bytes; i++ )
912 {
913 if( GET_BYTE( X, i ) != 0 )
914 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
915 }
916 }
917
918 for( i = 0; i < bytes_to_copy; i++ )
919 buf[i] = GET_BYTE( X, i );
920
921 if( stored_bytes < buflen )
922 {
923 /* Write trailing 0 bytes */
924 memset( buf + stored_bytes, 0, buflen - stored_bytes );
925 }
926
927 return( 0 );
928}
929
930/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000931 * Export X into unsigned binary data, big endian
932 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100933int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
934 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000935{
Hanno Becker73d7d792018-12-11 10:35:51 +0000936 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100937 size_t bytes_to_copy;
938 unsigned char *p;
939 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000940
Hanno Becker73d7d792018-12-11 10:35:51 +0000941 MPI_VALIDATE_RET( X != NULL );
942 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
943
944 stored_bytes = X->n * ciL;
945
Gilles Peskine11cdb052018-11-20 16:47:47 +0100946 if( stored_bytes < buflen )
947 {
948 /* There is enough space in the output buffer. Write initial
949 * null bytes and record the position at which to start
950 * writing the significant bytes. In this case, the execution
951 * trace of this function does not depend on the value of the
952 * number. */
953 bytes_to_copy = stored_bytes;
954 p = buf + buflen - stored_bytes;
955 memset( buf, 0, buflen - stored_bytes );
956 }
957 else
958 {
959 /* The output buffer is smaller than the allocated size of X.
960 * However X may fit if its leading bytes are zero. */
961 bytes_to_copy = buflen;
962 p = buf;
963 for( i = bytes_to_copy; i < stored_bytes; i++ )
964 {
965 if( GET_BYTE( X, i ) != 0 )
966 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
967 }
968 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000969
Gilles Peskine11cdb052018-11-20 16:47:47 +0100970 for( i = 0; i < bytes_to_copy; i++ )
971 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000972
973 return( 0 );
974}
975
976/*
977 * Left-shift: X <<= count
978 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200979int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000980{
Paul Bakker23986e52011-04-24 08:57:21 +0000981 int ret;
982 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200983 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000984 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000985
986 v0 = count / (biL );
987 t1 = count & (biL - 1);
988
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200989 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000990
Paul Bakkerf9688572011-05-05 10:00:45 +0000991 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200992 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000993
994 ret = 0;
995
996 /*
997 * shift by count / limb_size
998 */
999 if( v0 > 0 )
1000 {
Paul Bakker23986e52011-04-24 08:57:21 +00001001 for( i = X->n; i > v0; i-- )
1002 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001003
Paul Bakker23986e52011-04-24 08:57:21 +00001004 for( ; i > 0; i-- )
1005 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001006 }
1007
1008 /*
1009 * shift by count % limb_size
1010 */
1011 if( t1 > 0 )
1012 {
1013 for( i = v0; i < X->n; i++ )
1014 {
1015 r1 = X->p[i] >> (biL - t1);
1016 X->p[i] <<= t1;
1017 X->p[i] |= r0;
1018 r0 = r1;
1019 }
1020 }
1021
1022cleanup:
1023
1024 return( ret );
1025}
1026
1027/*
1028 * Right-shift: X >>= count
1029 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001030int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001031{
Paul Bakker23986e52011-04-24 08:57:21 +00001032 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001033 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001034 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001035
1036 v0 = count / biL;
1037 v1 = count & (biL - 1);
1038
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001039 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001040 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001041
Paul Bakker5121ce52009-01-03 21:22:43 +00001042 /*
1043 * shift by count / limb_size
1044 */
1045 if( v0 > 0 )
1046 {
1047 for( i = 0; i < X->n - v0; i++ )
1048 X->p[i] = X->p[i + v0];
1049
1050 for( ; i < X->n; i++ )
1051 X->p[i] = 0;
1052 }
1053
1054 /*
1055 * shift by count % limb_size
1056 */
1057 if( v1 > 0 )
1058 {
Paul Bakker23986e52011-04-24 08:57:21 +00001059 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001060 {
Paul Bakker23986e52011-04-24 08:57:21 +00001061 r1 = X->p[i - 1] << (biL - v1);
1062 X->p[i - 1] >>= v1;
1063 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001064 r0 = r1;
1065 }
1066 }
1067
1068 return( 0 );
1069}
1070
1071/*
1072 * Compare unsigned values
1073 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001074int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001075{
Paul Bakker23986e52011-04-24 08:57:21 +00001076 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001077 MPI_VALIDATE_RET( X != NULL );
1078 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001079
Paul Bakker23986e52011-04-24 08:57:21 +00001080 for( i = X->n; i > 0; i-- )
1081 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001082 break;
1083
Paul Bakker23986e52011-04-24 08:57:21 +00001084 for( j = Y->n; j > 0; j-- )
1085 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001086 break;
1087
Paul Bakker23986e52011-04-24 08:57:21 +00001088 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001089 return( 0 );
1090
1091 if( i > j ) return( 1 );
1092 if( j > i ) return( -1 );
1093
Paul Bakker23986e52011-04-24 08:57:21 +00001094 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001095 {
Paul Bakker23986e52011-04-24 08:57:21 +00001096 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1097 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001098 }
1099
1100 return( 0 );
1101}
1102
1103/*
1104 * Compare signed values
1105 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001106int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001107{
Paul Bakker23986e52011-04-24 08:57:21 +00001108 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001109 MPI_VALIDATE_RET( X != NULL );
1110 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001111
Paul Bakker23986e52011-04-24 08:57:21 +00001112 for( i = X->n; i > 0; i-- )
1113 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001114 break;
1115
Paul Bakker23986e52011-04-24 08:57:21 +00001116 for( j = Y->n; j > 0; j-- )
1117 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001118 break;
1119
Paul Bakker23986e52011-04-24 08:57:21 +00001120 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001121 return( 0 );
1122
1123 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001124 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001125
1126 if( X->s > 0 && Y->s < 0 ) return( 1 );
1127 if( Y->s > 0 && X->s < 0 ) return( -1 );
1128
Paul Bakker23986e52011-04-24 08:57:21 +00001129 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001130 {
Paul Bakker23986e52011-04-24 08:57:21 +00001131 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1132 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001133 }
1134
1135 return( 0 );
1136}
1137
1138/*
1139 * Compare signed values
1140 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001141int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001142{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001143 mbedtls_mpi Y;
1144 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001145 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001146
1147 *p = ( z < 0 ) ? -z : z;
1148 Y.s = ( z < 0 ) ? -1 : 1;
1149 Y.n = 1;
1150 Y.p = p;
1151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001152 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001153}
1154
1155/*
1156 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1157 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001158int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001159{
Paul Bakker23986e52011-04-24 08:57:21 +00001160 int ret;
1161 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001162 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001163 MPI_VALIDATE_RET( X != NULL );
1164 MPI_VALIDATE_RET( A != NULL );
1165 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001166
1167 if( X == B )
1168 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001169 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001170 }
1171
1172 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001173 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001174
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001175 /*
1176 * X should always be positive as a result of unsigned additions.
1177 */
1178 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001179
Paul Bakker23986e52011-04-24 08:57:21 +00001180 for( j = B->n; j > 0; j-- )
1181 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001182 break;
1183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001184 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001185
1186 o = B->p; p = X->p; c = 0;
1187
Janos Follath6c922682015-10-30 17:43:11 +01001188 /*
1189 * tmp is used because it might happen that p == o
1190 */
Paul Bakker23986e52011-04-24 08:57:21 +00001191 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001192 {
Janos Follath6c922682015-10-30 17:43:11 +01001193 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001194 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001195 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001196 }
1197
1198 while( c != 0 )
1199 {
1200 if( i >= X->n )
1201 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001202 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001203 p = X->p + i;
1204 }
1205
Paul Bakker2d319fd2012-09-16 21:34:26 +00001206 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001207 }
1208
1209cleanup:
1210
1211 return( ret );
1212}
1213
1214/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001215 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001216 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001217static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001218{
Paul Bakker23986e52011-04-24 08:57:21 +00001219 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001220 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001221
1222 for( i = c = 0; i < n; i++, s++, d++ )
1223 {
1224 z = ( *d < c ); *d -= c;
1225 c = ( *d < *s ) + z; *d -= *s;
1226 }
1227
1228 while( c != 0 )
1229 {
1230 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001231 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001232 }
1233}
1234
1235/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001236 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001237 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001238int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001239{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001240 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001241 int ret;
1242 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001243 MPI_VALIDATE_RET( X != NULL );
1244 MPI_VALIDATE_RET( A != NULL );
1245 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001246
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001247 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1248 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001249
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001250 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001251
1252 if( X == B )
1253 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001254 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001255 B = &TB;
1256 }
1257
1258 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001259 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001260
Paul Bakker1ef7a532009-06-20 10:50:55 +00001261 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001262 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001263 */
1264 X->s = 1;
1265
Paul Bakker5121ce52009-01-03 21:22:43 +00001266 ret = 0;
1267
Paul Bakker23986e52011-04-24 08:57:21 +00001268 for( n = B->n; n > 0; n-- )
1269 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001270 break;
1271
Paul Bakker23986e52011-04-24 08:57:21 +00001272 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001273
1274cleanup:
1275
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001276 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001277
1278 return( ret );
1279}
1280
1281/*
1282 * Signed addition: X = A + B
1283 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001284int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001285{
Hanno Becker73d7d792018-12-11 10:35:51 +00001286 int ret, s;
1287 MPI_VALIDATE_RET( X != NULL );
1288 MPI_VALIDATE_RET( A != NULL );
1289 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001290
Hanno Becker73d7d792018-12-11 10:35:51 +00001291 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001292 if( A->s * B->s < 0 )
1293 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001294 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001295 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001296 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001297 X->s = s;
1298 }
1299 else
1300 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001301 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001302 X->s = -s;
1303 }
1304 }
1305 else
1306 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001307 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001308 X->s = s;
1309 }
1310
1311cleanup:
1312
1313 return( ret );
1314}
1315
1316/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001317 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001318 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001319int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001320{
Hanno Becker73d7d792018-12-11 10:35:51 +00001321 int ret, s;
1322 MPI_VALIDATE_RET( X != NULL );
1323 MPI_VALIDATE_RET( A != NULL );
1324 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001325
Hanno Becker73d7d792018-12-11 10:35:51 +00001326 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001327 if( A->s * B->s > 0 )
1328 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001329 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001330 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001331 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001332 X->s = s;
1333 }
1334 else
1335 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001337 X->s = -s;
1338 }
1339 }
1340 else
1341 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001342 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001343 X->s = s;
1344 }
1345
1346cleanup:
1347
1348 return( ret );
1349}
1350
1351/*
1352 * Signed addition: X = A + b
1353 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001354int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001355{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001356 mbedtls_mpi _B;
1357 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001358 MPI_VALIDATE_RET( X != NULL );
1359 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001360
1361 p[0] = ( b < 0 ) ? -b : b;
1362 _B.s = ( b < 0 ) ? -1 : 1;
1363 _B.n = 1;
1364 _B.p = p;
1365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001367}
1368
1369/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001370 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001371 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001373{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001374 mbedtls_mpi _B;
1375 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001376 MPI_VALIDATE_RET( X != NULL );
1377 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001378
1379 p[0] = ( b < 0 ) ? -b : b;
1380 _B.s = ( b < 0 ) ? -1 : 1;
1381 _B.n = 1;
1382 _B.p = p;
1383
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001384 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001385}
1386
1387/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001388 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001389 */
1390static
1391#if defined(__APPLE__) && defined(__arm__)
1392/*
1393 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1394 * appears to need this to prevent bad ARM code generation at -O3.
1395 */
1396__attribute__ ((noinline))
1397#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001398void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001399{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001401
1402#if defined(MULADDC_HUIT)
1403 for( ; i >= 8; i -= 8 )
1404 {
1405 MULADDC_INIT
1406 MULADDC_HUIT
1407 MULADDC_STOP
1408 }
1409
1410 for( ; i > 0; i-- )
1411 {
1412 MULADDC_INIT
1413 MULADDC_CORE
1414 MULADDC_STOP
1415 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001416#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001417 for( ; i >= 16; i -= 16 )
1418 {
1419 MULADDC_INIT
1420 MULADDC_CORE MULADDC_CORE
1421 MULADDC_CORE MULADDC_CORE
1422 MULADDC_CORE MULADDC_CORE
1423 MULADDC_CORE MULADDC_CORE
1424
1425 MULADDC_CORE MULADDC_CORE
1426 MULADDC_CORE MULADDC_CORE
1427 MULADDC_CORE MULADDC_CORE
1428 MULADDC_CORE MULADDC_CORE
1429 MULADDC_STOP
1430 }
1431
1432 for( ; i >= 8; i -= 8 )
1433 {
1434 MULADDC_INIT
1435 MULADDC_CORE MULADDC_CORE
1436 MULADDC_CORE MULADDC_CORE
1437
1438 MULADDC_CORE MULADDC_CORE
1439 MULADDC_CORE MULADDC_CORE
1440 MULADDC_STOP
1441 }
1442
1443 for( ; i > 0; i-- )
1444 {
1445 MULADDC_INIT
1446 MULADDC_CORE
1447 MULADDC_STOP
1448 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001449#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001450
1451 t++;
1452
1453 do {
1454 *d += c; c = ( *d < c ); d++;
1455 }
1456 while( c != 0 );
1457}
1458
1459/*
1460 * Baseline multiplication: X = A * B (HAC 14.12)
1461 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001462int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001463{
Paul Bakker23986e52011-04-24 08:57:21 +00001464 int ret;
1465 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001467 MPI_VALIDATE_RET( X != NULL );
1468 MPI_VALIDATE_RET( A != NULL );
1469 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001473 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1474 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001475
Paul Bakker23986e52011-04-24 08:57:21 +00001476 for( i = A->n; i > 0; i-- )
1477 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001478 break;
1479
Paul Bakker23986e52011-04-24 08:57:21 +00001480 for( j = B->n; j > 0; j-- )
1481 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001482 break;
1483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001484 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1485 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001486
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001487 for( ; j > 0; j-- )
1488 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001489
1490 X->s = A->s * B->s;
1491
1492cleanup:
1493
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001494 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001495
1496 return( ret );
1497}
1498
1499/*
1500 * Baseline multiplication: X = A * b
1501 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001502int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001503{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001504 mbedtls_mpi _B;
1505 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001506 MPI_VALIDATE_RET( X != NULL );
1507 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001508
1509 _B.s = 1;
1510 _B.n = 1;
1511 _B.p = p;
1512 p[0] = b;
1513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001514 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001515}
1516
1517/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001518 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1519 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001520 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001521static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1522 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001523{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001524#if defined(MBEDTLS_HAVE_UDBL)
1525 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001526#else
Simon Butcher9803d072016-01-03 00:24:34 +00001527 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1528 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001529 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1530 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001531 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001532#endif
1533
Simon Butcher15b15d12015-11-26 19:35:03 +00001534 /*
1535 * Check for overflow
1536 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001537 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001538 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001539 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001540
Simon Butcherf5ba0452015-12-27 23:01:55 +00001541 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001542 }
1543
1544#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001545 dividend = (mbedtls_t_udbl) u1 << biL;
1546 dividend |= (mbedtls_t_udbl) u0;
1547 quotient = dividend / d;
1548 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1549 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1550
1551 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001552 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001553
1554 return (mbedtls_mpi_uint) quotient;
1555#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001556
1557 /*
1558 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1559 * Vol. 2 - Seminumerical Algorithms, Knuth
1560 */
1561
1562 /*
1563 * Normalize the divisor, d, and dividend, u0, u1
1564 */
1565 s = mbedtls_clz( d );
1566 d = d << s;
1567
1568 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001569 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001570 u0 = u0 << s;
1571
1572 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001573 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001574
1575 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001576 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001577
1578 /*
1579 * Find the first quotient and remainder
1580 */
1581 q1 = u1 / d1;
1582 r0 = u1 - d1 * q1;
1583
1584 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1585 {
1586 q1 -= 1;
1587 r0 += d1;
1588
1589 if ( r0 >= radix ) break;
1590 }
1591
Simon Butcherf5ba0452015-12-27 23:01:55 +00001592 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001593 q0 = rAX / d1;
1594 r0 = rAX - q0 * d1;
1595
1596 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1597 {
1598 q0 -= 1;
1599 r0 += d1;
1600
1601 if ( r0 >= radix ) break;
1602 }
1603
1604 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001605 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001606
1607 quotient = q1 * radix + q0;
1608
1609 return quotient;
1610#endif
1611}
1612
1613/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001614 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001615 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001616int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1617 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001618{
Paul Bakker23986e52011-04-24 08:57:21 +00001619 int ret;
1620 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001621 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001622 MPI_VALIDATE_RET( A != NULL );
1623 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001624
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001625 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1626 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001627
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001628 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1629 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001630
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001631 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001632 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001633 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1634 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001635 return( 0 );
1636 }
1637
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001638 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1639 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001640 X.s = Y.s = 1;
1641
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001642 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1643 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1644 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1645 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001646
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001647 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001648 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001649 {
1650 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1652 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001653 }
1654 else k = 0;
1655
1656 n = X.n - 1;
1657 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001658 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001659
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001660 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001661 {
1662 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001663 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001664 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001665 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001666
1667 for( i = n; i > t ; i-- )
1668 {
1669 if( X.p[i] >= Y.p[t] )
1670 Z.p[i - t - 1] = ~0;
1671 else
1672 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001673 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1674 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001675 }
1676
1677 Z.p[i - t - 1]++;
1678 do
1679 {
1680 Z.p[i - t - 1]--;
1681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001682 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001683 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001684 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001685 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001686
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001687 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001688 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1689 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001690 T2.p[2] = X.p[i];
1691 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001692 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001693
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001694 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1695 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1696 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001697
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001698 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001699 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001700 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1701 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1702 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001703 Z.p[i - t - 1]--;
1704 }
1705 }
1706
1707 if( Q != NULL )
1708 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001709 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001710 Q->s = A->s * B->s;
1711 }
1712
1713 if( R != NULL )
1714 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001715 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001716 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001717 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001718
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001719 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001720 R->s = 1;
1721 }
1722
1723cleanup:
1724
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001725 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1726 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001727
1728 return( ret );
1729}
1730
1731/*
1732 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001733 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001734int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1735 const mbedtls_mpi *A,
1736 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001737{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001738 mbedtls_mpi _B;
1739 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001740 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001741
1742 p[0] = ( b < 0 ) ? -b : b;
1743 _B.s = ( b < 0 ) ? -1 : 1;
1744 _B.n = 1;
1745 _B.p = p;
1746
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001747 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001748}
1749
1750/*
1751 * Modulo: R = A mod B
1752 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001753int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001754{
1755 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001756 MPI_VALIDATE_RET( R != NULL );
1757 MPI_VALIDATE_RET( A != NULL );
1758 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001759
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001760 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1761 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001762
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001763 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001764
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001765 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1766 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001767
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001768 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1769 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001770
1771cleanup:
1772
1773 return( ret );
1774}
1775
1776/*
1777 * Modulo: r = A mod b
1778 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001779int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001780{
Paul Bakker23986e52011-04-24 08:57:21 +00001781 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001782 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001783 MPI_VALIDATE_RET( r != NULL );
1784 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001785
1786 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001787 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001788
1789 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001790 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001791
1792 /*
1793 * handle trivial cases
1794 */
1795 if( b == 1 )
1796 {
1797 *r = 0;
1798 return( 0 );
1799 }
1800
1801 if( b == 2 )
1802 {
1803 *r = A->p[0] & 1;
1804 return( 0 );
1805 }
1806
1807 /*
1808 * general case
1809 */
Paul Bakker23986e52011-04-24 08:57:21 +00001810 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001811 {
Paul Bakker23986e52011-04-24 08:57:21 +00001812 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001813 y = ( y << biH ) | ( x >> biH );
1814 z = y / b;
1815 y -= z * b;
1816
1817 x <<= biH;
1818 y = ( y << biH ) | ( x >> biH );
1819 z = y / b;
1820 y -= z * b;
1821 }
1822
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001823 /*
1824 * If A is negative, then the current y represents a negative value.
1825 * Flipping it to the positive side.
1826 */
1827 if( A->s < 0 && y != 0 )
1828 y = b - y;
1829
Paul Bakker5121ce52009-01-03 21:22:43 +00001830 *r = y;
1831
1832 return( 0 );
1833}
1834
1835/*
1836 * Fast Montgomery initialization (thanks to Tom St Denis)
1837 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001838static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001839{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001840 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001841 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001842
1843 x = m0;
1844 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001845
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001846 for( i = biL; i >= 8; i /= 2 )
1847 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001848
1849 *mm = ~x + 1;
1850}
1851
1852/*
1853 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1854 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001855static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001856 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001857{
Paul Bakker23986e52011-04-24 08:57:21 +00001858 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001859 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001860
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001861 if( T->n < N->n + 1 || T->p == NULL )
1862 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1863
Paul Bakker5121ce52009-01-03 21:22:43 +00001864 memset( T->p, 0, T->n * ciL );
1865
1866 d = T->p;
1867 n = N->n;
1868 m = ( B->n < n ) ? B->n : n;
1869
1870 for( i = 0; i < n; i++ )
1871 {
1872 /*
1873 * T = (T + u0*B + u1*N) / 2^biL
1874 */
1875 u0 = A->p[i];
1876 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1877
1878 mpi_mul_hlp( m, B->p, d, u0 );
1879 mpi_mul_hlp( n, N->p, d, u1 );
1880
1881 *d++ = u0; d[n + 1] = 0;
1882 }
1883
Paul Bakker66d5d072014-06-17 16:39:18 +02001884 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001885
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001886 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001887 mpi_sub_hlp( n, N->p, A->p );
1888 else
1889 /* prevent timing attacks */
1890 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001891
1892 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001893}
1894
1895/*
1896 * Montgomery reduction: A = A * R^-1 mod N
1897 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001898static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1899 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001900{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001901 mbedtls_mpi_uint z = 1;
1902 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001903
Paul Bakker8ddb6452013-02-27 14:56:33 +01001904 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001905 U.p = &z;
1906
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001907 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001908}
1909
1910/*
1911 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1912 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001913int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1914 const mbedtls_mpi *E, const mbedtls_mpi *N,
1915 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001916{
Paul Bakker23986e52011-04-24 08:57:21 +00001917 int ret;
1918 size_t wbits, wsize, one = 1;
1919 size_t i, j, nblimbs;
1920 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001921 mbedtls_mpi_uint ei, mm, state;
1922 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001923 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001924
Hanno Becker73d7d792018-12-11 10:35:51 +00001925 MPI_VALIDATE_RET( X != NULL );
1926 MPI_VALIDATE_RET( A != NULL );
1927 MPI_VALIDATE_RET( E != NULL );
1928 MPI_VALIDATE_RET( N != NULL );
1929
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001930 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001931 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001932
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001933 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1934 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001935
1936 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001937 * Init temps and window size
1938 */
1939 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001940 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1941 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001942 memset( W, 0, sizeof( W ) );
1943
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001944 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
1946 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1947 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1948
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001949#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001950 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1951 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001952#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001953
Paul Bakker5121ce52009-01-03 21:22:43 +00001954 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001955 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1956 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1957 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001958
1959 /*
Paul Bakker50546922012-05-19 08:40:49 +00001960 * Compensate for negative A (and correct at the end)
1961 */
1962 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001963 if( neg )
1964 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001965 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001966 Apos.s = 1;
1967 A = &Apos;
1968 }
1969
1970 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001971 * If 1st call, pre-compute R^2 mod N
1972 */
1973 if( _RR == NULL || _RR->p == NULL )
1974 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001975 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1976 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1977 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001978
1979 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001980 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001981 }
1982 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001983 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001984
1985 /*
1986 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1987 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1989 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001990 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001991 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001992
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001993 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001994
1995 /*
1996 * X = R^2 * R^-1 mod N = R mod N
1997 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001998 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001999 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002000
2001 if( wsize > 1 )
2002 {
2003 /*
2004 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2005 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002006 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002007
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002008 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2009 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002010
2011 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002012 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002013
Paul Bakker5121ce52009-01-03 21:22:43 +00002014 /*
2015 * W[i] = W[i - 1] * W[1]
2016 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002017 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002018 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002019 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2020 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002021
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002022 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002023 }
2024 }
2025
2026 nblimbs = E->n;
2027 bufsize = 0;
2028 nbits = 0;
2029 wbits = 0;
2030 state = 0;
2031
2032 while( 1 )
2033 {
2034 if( bufsize == 0 )
2035 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002036 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002037 break;
2038
Paul Bakker0d7702c2013-10-29 16:18:35 +01002039 nblimbs--;
2040
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002041 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002042 }
2043
2044 bufsize--;
2045
2046 ei = (E->p[nblimbs] >> bufsize) & 1;
2047
2048 /*
2049 * skip leading 0s
2050 */
2051 if( ei == 0 && state == 0 )
2052 continue;
2053
2054 if( ei == 0 && state == 1 )
2055 {
2056 /*
2057 * out of window, square X
2058 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002059 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002060 continue;
2061 }
2062
2063 /*
2064 * add ei to current window
2065 */
2066 state = 2;
2067
2068 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002069 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002070
2071 if( nbits == wsize )
2072 {
2073 /*
2074 * X = X^wsize R^-1 mod N
2075 */
2076 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002077 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002078
2079 /*
2080 * X = X * W[wbits] R^-1 mod N
2081 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002082 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002083
2084 state--;
2085 nbits = 0;
2086 wbits = 0;
2087 }
2088 }
2089
2090 /*
2091 * process the remaining bits
2092 */
2093 for( i = 0; i < nbits; i++ )
2094 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002095 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002096
2097 wbits <<= 1;
2098
Paul Bakker66d5d072014-06-17 16:39:18 +02002099 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002100 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002101 }
2102
2103 /*
2104 * X = A^E * R * R^-1 mod N = A^E mod N
2105 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002106 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002107
Hanno Beckera4af1c42017-04-18 09:07:45 +01002108 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002109 {
2110 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002111 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002112 }
2113
Paul Bakker5121ce52009-01-03 21:22:43 +00002114cleanup:
2115
Paul Bakker66d5d072014-06-17 16:39:18 +02002116 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002117 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002119 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002120
Paul Bakker75a28602014-03-31 12:08:17 +02002121 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002122 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002123
2124 return( ret );
2125}
2126
Paul Bakker5121ce52009-01-03 21:22:43 +00002127/*
2128 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2129 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002130int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002131{
Paul Bakker23986e52011-04-24 08:57:21 +00002132 int ret;
2133 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002134 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002135
Hanno Becker73d7d792018-12-11 10:35:51 +00002136 MPI_VALIDATE_RET( G != NULL );
2137 MPI_VALIDATE_RET( A != NULL );
2138 MPI_VALIDATE_RET( B != NULL );
2139
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002140 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002141
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002142 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2143 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145 lz = mbedtls_mpi_lsb( &TA );
2146 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002147
Paul Bakker66d5d072014-06-17 16:39:18 +02002148 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002149 lz = lzt;
2150
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002151 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2152 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002153
Paul Bakker5121ce52009-01-03 21:22:43 +00002154 TA.s = TB.s = 1;
2155
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002156 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002157 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002158 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2159 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002160
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002161 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002162 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002163 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2164 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002165 }
2166 else
2167 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002168 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2169 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002170 }
2171 }
2172
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002173 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2174 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002175
2176cleanup:
2177
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002178 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002179
2180 return( ret );
2181}
2182
Paul Bakker33dc46b2014-04-30 16:11:39 +02002183/*
2184 * Fill X with size bytes of random.
2185 *
2186 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002187 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002188 * deterministic, eg for tests).
2189 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002190int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002191 int (*f_rng)(void *, unsigned char *, size_t),
2192 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002193{
Paul Bakker23986e52011-04-24 08:57:21 +00002194 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002195 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002196 size_t const overhead = ( limbs * ciL ) - size;
2197 unsigned char *Xp;
2198
Hanno Becker8ce11a32018-12-19 16:18:52 +00002199 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002200 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002201
Hanno Beckerda1655a2017-10-18 14:21:44 +01002202 /* Ensure that target MPI has exactly the necessary number of limbs */
2203 if( X->n != limbs )
2204 {
2205 mbedtls_mpi_free( X );
2206 mbedtls_mpi_init( X );
2207 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2208 }
2209 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002210
Hanno Beckerda1655a2017-10-18 14:21:44 +01002211 Xp = (unsigned char*) X->p;
2212 f_rng( p_rng, Xp + overhead, size );
2213
Hanno Becker2be8a552018-10-25 12:40:09 +01002214 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002215
2216cleanup:
2217 return( ret );
2218}
2219
Paul Bakker5121ce52009-01-03 21:22:43 +00002220/*
2221 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2222 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002223int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002224{
2225 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002226 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002227 MPI_VALIDATE_RET( X != NULL );
2228 MPI_VALIDATE_RET( A != NULL );
2229 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002230
Hanno Becker4bcb4912017-04-18 15:49:39 +01002231 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002232 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002233
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002234 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2235 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2236 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002237
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002238 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002239
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002240 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002241 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002242 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002243 goto cleanup;
2244 }
2245
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002246 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2247 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2248 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2249 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002250
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002251 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2252 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2253 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2254 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002255
2256 do
2257 {
2258 while( ( TU.p[0] & 1 ) == 0 )
2259 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002260 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002261
2262 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2263 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2265 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002266 }
2267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002268 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2269 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002270 }
2271
2272 while( ( TV.p[0] & 1 ) == 0 )
2273 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002274 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002275
2276 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2277 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002278 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2279 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002280 }
2281
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002282 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2283 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002284 }
2285
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002286 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002287 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2289 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2290 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002291 }
2292 else
2293 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002294 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2295 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2296 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002297 }
2298 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002300
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002301 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2302 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002303
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002304 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2305 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002308
2309cleanup:
2310
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002311 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2312 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2313 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002314
2315 return( ret );
2316}
2317
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002318#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002319
Paul Bakker5121ce52009-01-03 21:22:43 +00002320static const int small_prime[] =
2321{
2322 3, 5, 7, 11, 13, 17, 19, 23,
2323 29, 31, 37, 41, 43, 47, 53, 59,
2324 61, 67, 71, 73, 79, 83, 89, 97,
2325 101, 103, 107, 109, 113, 127, 131, 137,
2326 139, 149, 151, 157, 163, 167, 173, 179,
2327 181, 191, 193, 197, 199, 211, 223, 227,
2328 229, 233, 239, 241, 251, 257, 263, 269,
2329 271, 277, 281, 283, 293, 307, 311, 313,
2330 317, 331, 337, 347, 349, 353, 359, 367,
2331 373, 379, 383, 389, 397, 401, 409, 419,
2332 421, 431, 433, 439, 443, 449, 457, 461,
2333 463, 467, 479, 487, 491, 499, 503, 509,
2334 521, 523, 541, 547, 557, 563, 569, 571,
2335 577, 587, 593, 599, 601, 607, 613, 617,
2336 619, 631, 641, 643, 647, 653, 659, 661,
2337 673, 677, 683, 691, 701, 709, 719, 727,
2338 733, 739, 743, 751, 757, 761, 769, 773,
2339 787, 797, 809, 811, 821, 823, 827, 829,
2340 839, 853, 857, 859, 863, 877, 881, 883,
2341 887, 907, 911, 919, 929, 937, 941, 947,
2342 953, 967, 971, 977, 983, 991, 997, -103
2343};
2344
2345/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002346 * Small divisors test (X must be positive)
2347 *
2348 * Return values:
2349 * 0: no small factor (possible prime, more tests needed)
2350 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002351 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002352 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002353 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002354static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002355{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002356 int ret = 0;
2357 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002358 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002359
Paul Bakker5121ce52009-01-03 21:22:43 +00002360 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002361 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002362
2363 for( i = 0; small_prime[i] > 0; i++ )
2364 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002365 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002366 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002367
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002368 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002369
2370 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002371 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002372 }
2373
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002374cleanup:
2375 return( ret );
2376}
2377
2378/*
2379 * Miller-Rabin pseudo-primality test (HAC 4.24)
2380 */
Janos Follathda31fa12018-09-03 14:45:23 +01002381static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002382 int (*f_rng)(void *, unsigned char *, size_t),
2383 void *p_rng )
2384{
Pascal Junodb99183d2015-03-11 16:49:45 +01002385 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002386 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002387 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002388
Hanno Becker8ce11a32018-12-19 16:18:52 +00002389 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002390 MPI_VALIDATE_RET( f_rng != NULL );
2391
2392 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2393 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002394 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002395
Paul Bakker5121ce52009-01-03 21:22:43 +00002396 /*
2397 * W = |X| - 1
2398 * R = W >> lsb( W )
2399 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002400 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2401 s = mbedtls_mpi_lsb( &W );
2402 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2403 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002404
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002405 i = mbedtls_mpi_bitlen( X );
Janos Follathf301d232018-08-14 13:34:01 +01002406
Janos Follathda31fa12018-09-03 14:45:23 +01002407 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002408 {
2409 /*
2410 * pick a random A, 1 < A < |X| - 1
2411 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002412 count = 0;
2413 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002414 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002415
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002416 j = mbedtls_mpi_bitlen( &A );
2417 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002418 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002419 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002420 }
2421
2422 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002423 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002424 }
2425
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002426 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2427 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002428
2429 /*
2430 * A = A^R mod |X|
2431 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002432 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2435 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002436 continue;
2437
2438 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002439 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002440 {
2441 /*
2442 * A = A * A mod |X|
2443 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002444 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2445 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002446
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002447 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002448 break;
2449
2450 j++;
2451 }
2452
2453 /*
2454 * not prime if A != |X| - 1 or A == 1
2455 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002456 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2457 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002458 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002459 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002460 break;
2461 }
2462 }
2463
2464cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002465 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2466 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002467 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002468
2469 return( ret );
2470}
2471
2472/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002473 * Pseudo-primality test: small factors, then Miller-Rabin
2474 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002475int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2476 int (*f_rng)(void *, unsigned char *, size_t),
2477 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002478{
2479 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002480 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002481 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002482 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002483
2484 XX.s = 1;
2485 XX.n = X->n;
2486 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002487
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002488 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2489 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2490 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002492 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002493 return( 0 );
2494
2495 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2496 {
2497 if( ret == 1 )
2498 return( 0 );
2499
2500 return( ret );
2501 }
2502
Janos Follathda31fa12018-09-03 14:45:23 +01002503 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002504}
2505
Janos Follatha0b67c22018-09-18 14:48:23 +01002506#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002507/*
2508 * Pseudo-primality test, error probability 2^-80
2509 */
2510int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2511 int (*f_rng)(void *, unsigned char *, size_t),
2512 void *p_rng )
2513{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002514 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002515 MPI_VALIDATE_RET( f_rng != NULL );
2516
Janos Follatha0b67c22018-09-18 14:48:23 +01002517 /*
2518 * In the past our key generation aimed for an error rate of at most
2519 * 2^-80. Since this function is deprecated, aim for the same certainty
2520 * here as well.
2521 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002522 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002523}
Janos Follatha0b67c22018-09-18 14:48:23 +01002524#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002525
2526/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002527 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002528 *
Janos Follathf301d232018-08-14 13:34:01 +01002529 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2530 * be either 1024 bits or 1536 bits long, and flags must contain
2531 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002532 */
Janos Follath7c025a92018-08-14 11:08:41 +01002533int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002534 int (*f_rng)(void *, unsigned char *, size_t),
2535 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002536{
Jethro Beekman66689272018-02-14 19:24:10 -08002537#ifdef MBEDTLS_HAVE_INT64
2538// ceil(2^63.5)
2539#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2540#else
2541// ceil(2^31.5)
2542#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2543#endif
2544 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002545 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002546 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002547 mbedtls_mpi_uint r;
2548 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002549
Hanno Becker8ce11a32018-12-19 16:18:52 +00002550 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002551 MPI_VALIDATE_RET( f_rng != NULL );
2552
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002553 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2554 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002555
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002556 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002557
2558 n = BITS_TO_LIMBS( nbits );
2559
Janos Follathda31fa12018-09-03 14:45:23 +01002560 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2561 {
2562 /*
2563 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2564 */
2565 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2566 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2567 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2568 }
2569 else
2570 {
2571 /*
2572 * 2^-100 error probability, number of rounds computed based on HAC,
2573 * fact 4.48
2574 */
2575 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2576 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2577 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2578 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2579 }
2580
Jethro Beekman66689272018-02-14 19:24:10 -08002581 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002582 {
Jethro Beekman66689272018-02-14 19:24:10 -08002583 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2584 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2585 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2586
2587 k = n * biL;
2588 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2589 X->p[0] |= 1;
2590
Janos Follath7c025a92018-08-14 11:08:41 +01002591 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002592 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002593 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002594
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002595 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002596 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002597 }
Jethro Beekman66689272018-02-14 19:24:10 -08002598 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002599 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002600 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002601 * An necessary condition for Y and X = 2Y + 1 to be prime
2602 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2603 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002604 */
Jethro Beekman66689272018-02-14 19:24:10 -08002605
2606 X->p[0] |= 2;
2607
2608 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2609 if( r == 0 )
2610 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2611 else if( r == 1 )
2612 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2613
2614 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2615 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2616 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2617
2618 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002619 {
Jethro Beekman66689272018-02-14 19:24:10 -08002620 /*
2621 * First, check small factors for X and Y
2622 * before doing Miller-Rabin on any of them
2623 */
2624 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2625 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002626 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002627 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002628 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002629 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002630 goto cleanup;
2631
2632 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2633 goto cleanup;
2634
2635 /*
2636 * Next candidates. We want to preserve Y = (X-1) / 2 and
2637 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2638 * so up Y by 6 and X by 12.
2639 */
2640 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2641 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002642 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002643 }
2644 }
2645
2646cleanup:
2647
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002648 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002649
2650 return( ret );
2651}
2652
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002653#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002654
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002655#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002656
Paul Bakker23986e52011-04-24 08:57:21 +00002657#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002658
2659static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2660{
2661 { 693, 609, 21 },
2662 { 1764, 868, 28 },
2663 { 768454923, 542167814, 1 }
2664};
2665
Paul Bakker5121ce52009-01-03 21:22:43 +00002666/*
2667 * Checkup routine
2668 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002669int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002670{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002671 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002672 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002673
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002674 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2675 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002676
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002677 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002678 "EFE021C2645FD1DC586E69184AF4A31E" \
2679 "D5F53E93B5F123FA41680867BA110131" \
2680 "944FE7952E2517337780CB0DB80E61AA" \
2681 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2682
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002683 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002684 "B2E7EFD37075B9F03FF989C7C5051C20" \
2685 "34D2A323810251127E7BF8625A4F49A5" \
2686 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2687 "5B5C25763222FEFCCFC38B832366C29E" ) );
2688
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002689 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002690 "0066A198186C18C10B2F5ED9B522752A" \
2691 "9830B69916E535C8F047518A889A43A5" \
2692 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2693
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002694 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002695
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002696 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002697 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2698 "9E857EA95A03512E2BAE7391688D264A" \
2699 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2700 "8001B72E848A38CAE1C65F78E56ABDEF" \
2701 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2702 "ECF677152EF804370C1A305CAF3B5BF1" \
2703 "30879B56C61DE584A0F53A2447A51E" ) );
2704
2705 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002706 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002707
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002708 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002709 {
2710 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002711 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002712
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002713 ret = 1;
2714 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002715 }
2716
2717 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002718 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002719
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002720 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002721
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002722 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002723 "256567336059E52CAE22925474705F39A94" ) );
2724
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002725 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002726 "6613F26162223DF488E9CD48CC132C7A" \
2727 "0AC93C701B001B092E4E5B9F73BCD27B" \
2728 "9EE50D0657C77F374E903CDFA4C642" ) );
2729
2730 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002731 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002732
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002733 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2734 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002735 {
2736 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002737 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002738
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002739 ret = 1;
2740 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002741 }
2742
2743 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002744 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002745
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002746 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002747
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002748 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002749 "36E139AEA55215609D2816998ED020BB" \
2750 "BD96C37890F65171D948E9BC7CBAA4D9" \
2751 "325D24D6A3C12710F10A09FA08AB87" ) );
2752
2753 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002754 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002755
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002756 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002757 {
2758 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002759 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002760
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002761 ret = 1;
2762 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002763 }
2764
2765 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002766 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002767
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002768 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002769
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002770 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002771 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2772 "C3DBA76456363A10869622EAC2DD84EC" \
2773 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2774
2775 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002776 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002777
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002778 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002779 {
2780 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002781 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002782
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002783 ret = 1;
2784 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002785 }
2786
2787 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002788 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002789
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002790 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002791 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002792
Paul Bakker66d5d072014-06-17 16:39:18 +02002793 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002794 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002795 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2796 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002797
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002798 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002799
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002800 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002801 {
2802 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002803 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002804
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002805 ret = 1;
2806 goto cleanup;
2807 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002808 }
2809
2810 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002811 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002812
Paul Bakker5121ce52009-01-03 21:22:43 +00002813cleanup:
2814
2815 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002816 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002817
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002818 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2819 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002820
2821 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002822 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002823
2824 return( ret );
2825}
2826
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002827#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002828
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002829#endif /* MBEDTLS_BIGNUM_C */