blob: 39e718dcf73e85593e83dd601e8c92a5ba64f587 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050048#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000049
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <string.h>
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020054#else
Rich Evans00ab4702015-02-06 13:43:58 +000055#include <stdio.h>
56#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020058#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020060#endif
61
Hanno Becker73d7d792018-12-11 10:35:51 +000062#define MPI_VALIDATE_RET( cond ) \
63 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
64#define MPI_VALIDATE( cond ) \
65 MBEDTLS_INTERNAL_VALIDATE( cond )
66
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020067#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000068#define biL (ciL << 3) /* bits in limb */
69#define biH (ciL << 2) /* half limb size */
70
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010071#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
72
Paul Bakker5121ce52009-01-03 21:22:43 +000073/*
74 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020075 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000076 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020077#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
78#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000079
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050080/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050081static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
82{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050083 mbedtls_platform_zeroize( v, ciL * n );
84}
85
Paul Bakker5121ce52009-01-03 21:22:43 +000086/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000088 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000090{
Hanno Becker73d7d792018-12-11 10:35:51 +000091 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000092
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 X->s = 1;
94 X->n = 0;
95 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000096}
97
98/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000099 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000103 if( X == NULL )
104 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000105
Paul Bakker6c591fa2011-05-05 11:49:20 +0000106 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000107 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200108 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000110 }
111
Paul Bakker6c591fa2011-05-05 11:49:20 +0000112 X->s = 1;
113 X->n = 0;
114 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000115}
116
117/*
118 * Enlarge to the specified number of limbs
119 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000121{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000123 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200126 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000127
Paul Bakker5121ce52009-01-03 21:22:43 +0000128 if( X->n < nblimbs )
129 {
Simon Butcher29176892016-05-20 00:19:09 +0100130 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200131 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000132
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 if( X->p != NULL )
134 {
135 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200136 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000138 }
139
140 X->n = nblimbs;
141 X->p = p;
142 }
143
144 return( 0 );
145}
146
147/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100148 * Resize down as much as possible,
149 * while keeping at least the specified number of limbs
150 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000155 MPI_VALIDATE_RET( X != NULL );
156
157 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
158 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100159
160 /* Actually resize up in this case */
161 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163
164 for( i = X->n - 1; i > 0; i-- )
165 if( X->p[i] != 0 )
166 break;
167 i++;
168
169 if( i < nblimbs )
170 i = nblimbs;
171
Simon Butcher29176892016-05-20 00:19:09 +0100172 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200173 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100174
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175 if( X->p != NULL )
176 {
177 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200178 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100180 }
181
182 X->n = i;
183 X->p = p;
184
185 return( 0 );
186}
187
188/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000189 * Copy the contents of Y into X
190 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000192{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100193 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000194 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000195 MPI_VALIDATE_RET( X != NULL );
196 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000197
198 if( X == Y )
199 return( 0 );
200
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200201 if( Y->p == NULL )
202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200204 return( 0 );
205 }
206
Paul Bakker5121ce52009-01-03 21:22:43 +0000207 for( i = Y->n - 1; i > 0; i-- )
208 if( Y->p[i] != 0 )
209 break;
210 i++;
211
212 X->s = Y->s;
213
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100214 if( X->n < i )
215 {
216 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
217 }
218 else
219 {
220 memset( X->p + i, 0, ( X->n - i ) * ciL );
221 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
Paul Bakker5121ce52009-01-03 21:22:43 +0000223 memcpy( X->p, Y->p, i * ciL );
224
225cleanup:
226
227 return( ret );
228}
229
230/*
231 * Swap the contents of X and Y
232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000234{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000236 MPI_VALIDATE( X != NULL );
237 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 memcpy( &T, X, sizeof( mbedtls_mpi ) );
240 memcpy( X, Y, sizeof( mbedtls_mpi ) );
241 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000242}
243
244/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100245 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100246 * about whether the assignment was made or not.
247 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100248 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250{
251 int ret = 0;
252 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000253 MPI_VALIDATE_RET( X != NULL );
254 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100255
Pascal Junodb99183d2015-03-11 16:49:45 +0100256 /* make sure assign is 0 or 1 in a time-constant manner */
257 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100260
Paul Bakker66d5d072014-06-17 16:39:18 +0200261 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100262
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100263 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200264 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100265
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100266 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200267 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100268
269cleanup:
270 return( ret );
271}
272
273/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274 * Conditionally swap X and Y, without leaking information
275 * about whether the swap was made or not.
276 * Here it is not ok to simply swap the pointers, which whould lead to
277 * different memory access patterns when X and Y are used afterwards.
278 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100280{
281 int ret, s;
282 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000284 MPI_VALIDATE_RET( X != NULL );
285 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286
287 if( X == Y )
288 return( 0 );
289
Pascal Junodb99183d2015-03-11 16:49:45 +0100290 /* make sure swap is 0 or 1 in a time-constant manner */
291 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100295
296 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200297 X->s = X->s * ( 1 - swap ) + Y->s * swap;
298 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100299
300
301 for( i = 0; i < X->n; i++ )
302 {
303 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200304 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
305 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100306 }
307
308cleanup:
309 return( ret );
310}
311
312/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000313 * Set value from integer
314 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000316{
317 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +0000318 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200320 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000321 memset( X->p, 0, X->n * ciL );
322
323 X->p[0] = ( z < 0 ) ? -z : z;
324 X->s = ( z < 0 ) ? -1 : 1;
325
326cleanup:
327
328 return( ret );
329}
330
331/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332 * Get a specific bit
333 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000335{
Hanno Becker73d7d792018-12-11 10:35:51 +0000336 MPI_VALIDATE_RET( X != NULL );
337
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338 if( X->n * biL <= pos )
339 return( 0 );
340
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200341 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000342}
343
Gilles Peskine11cdb052018-11-20 16:47:47 +0100344/* Get a specific byte, without range checks. */
345#define GET_BYTE( X, i ) \
346 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
347
Paul Bakker2f5947e2011-05-18 15:47:11 +0000348/*
349 * Set a bit to a specific value of 0 or 1
350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000352{
353 int ret = 0;
354 size_t off = pos / biL;
355 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000356 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000357
358 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200360
Paul Bakker2f5947e2011-05-18 15:47:11 +0000361 if( X->n * biL <= pos )
362 {
363 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200364 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000367 }
368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
370 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000371
372cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200373
Paul Bakker2f5947e2011-05-18 15:47:11 +0000374 return( ret );
375}
376
377/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200378 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000381{
Paul Bakker23986e52011-04-24 08:57:21 +0000382 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000383 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000384
385 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000386 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
388 return( count );
389
390 return( 0 );
391}
392
393/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000394 * Count leading zero bits in a given integer
395 */
396static size_t mbedtls_clz( const mbedtls_mpi_uint x )
397{
398 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100399 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000400
401 for( j = 0; j < biL; j++ )
402 {
403 if( x & mask ) break;
404
405 mask >>= 1;
406 }
407
408 return j;
409}
410
411/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200412 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000413 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200414size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000415{
Paul Bakker23986e52011-04-24 08:57:21 +0000416 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200418 if( X->n == 0 )
419 return( 0 );
420
Paul Bakker5121ce52009-01-03 21:22:43 +0000421 for( i = X->n - 1; i > 0; i-- )
422 if( X->p[i] != 0 )
423 break;
424
Simon Butcher15b15d12015-11-26 19:35:03 +0000425 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
Paul Bakker23986e52011-04-24 08:57:21 +0000427 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000428}
429
430/*
431 * Return the total size in bytes
432 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000434{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200435 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000436}
437
438/*
439 * Convert an ASCII character to digit value
440 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000442{
443 *d = 255;
444
445 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
446 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
447 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 if( *d >= (mbedtls_mpi_uint) radix )
450 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000451
452 return( 0 );
453}
454
455/*
456 * Import from an ASCII string
457 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000459{
Paul Bakker23986e52011-04-24 08:57:21 +0000460 int ret;
461 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 mbedtls_mpi_uint d;
463 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000464 MPI_VALIDATE_RET( X != NULL );
465 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000466
467 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000468 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000471
Paul Bakkerff60ee62010-03-16 21:09:09 +0000472 slen = strlen( s );
473
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 if( radix == 16 )
475 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100476 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200477 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
478
Paul Bakkerff60ee62010-03-16 21:09:09 +0000479 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
482 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
Paul Bakker23986e52011-04-24 08:57:21 +0000484 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000485 {
Paul Bakker23986e52011-04-24 08:57:21 +0000486 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000487 {
488 X->s = -1;
489 break;
490 }
491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200493 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494 }
495 }
496 else
497 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
Paul Bakkerff60ee62010-03-16 21:09:09 +0000500 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000501 {
502 if( i == 0 && s[i] == '-' )
503 {
504 X->s = -1;
505 continue;
506 }
507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
509 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000510
511 if( X->s == 1 )
512 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000514 }
515 else
516 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000518 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000519 }
520 }
521
522cleanup:
523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000525
526 return( ret );
527}
528
529/*
Ron Eldora16fa292018-11-20 14:07:01 +0200530 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000531 */
Ron Eldora16fa292018-11-20 14:07:01 +0200532static int mpi_write_hlp( mbedtls_mpi *X, int radix,
533 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000534{
535 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200537 size_t length = 0;
538 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
Ron Eldora16fa292018-11-20 14:07:01 +0200540 do
541 {
542 if( length >= buflen )
543 {
544 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
545 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000546
Ron Eldora16fa292018-11-20 14:07:01 +0200547 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
548 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
549 /*
550 * Write the residue in the current position, as an ASCII character.
551 */
552 if( r < 0xA )
553 *(--p_end) = (char)( '0' + r );
554 else
555 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000556
Ron Eldora16fa292018-11-20 14:07:01 +0200557 length++;
558 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000559
Ron Eldora16fa292018-11-20 14:07:01 +0200560 memmove( *p, p_end, length );
561 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000562
563cleanup:
564
565 return( ret );
566}
567
568/*
569 * Export into an ASCII string
570 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100571int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
572 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000573{
Paul Bakker23986e52011-04-24 08:57:21 +0000574 int ret = 0;
575 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000576 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000578 MPI_VALIDATE_RET( X != NULL );
579 MPI_VALIDATE_RET( olen != NULL );
580 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000581
582 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000583 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000585 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
586 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
587 * `n`. If radix > 4, this might be a strict
588 * overapproximation of the number of
589 * radix-adic digits needed to present `n`. */
590 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
591 * present `n`. */
592
Janos Follath870ed002019-03-06 13:43:02 +0000593 n += 1; /* Terminating null byte */
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000594 n += 1; /* Compensate for the divisions above, which round down `n`
595 * in case it's not even. */
596 n += 1; /* Potential '-'-sign. */
597 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
598 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100600 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000601 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100602 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000604 }
605
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100606 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000608
609 if( X->s == -1 )
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000610 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000611 *p++ = '-';
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000612 buflen--;
613 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000614
615 if( radix == 16 )
616 {
Paul Bakker23986e52011-04-24 08:57:21 +0000617 int c;
618 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000619
Paul Bakker23986e52011-04-24 08:57:21 +0000620 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000621 {
Paul Bakker23986e52011-04-24 08:57:21 +0000622 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 {
Paul Bakker23986e52011-04-24 08:57:21 +0000624 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000625
Paul Bakker6c343d72014-07-10 14:36:19 +0200626 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000627 continue;
628
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000629 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000630 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000631 k = 1;
632 }
633 }
634 }
635 else
636 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000638
639 if( T.s == -1 )
640 T.s = 1;
641
Ron Eldora16fa292018-11-20 14:07:01 +0200642 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000643 }
644
645 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100646 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000647
648cleanup:
649
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000651
652 return( ret );
653}
654
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000656/*
657 * Read X from an opened file
658 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000660{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000662 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000663 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000664 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000665 * Buffer should have space for (short) label and decimal formatted MPI,
666 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000667 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200668 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000669
Hanno Becker73d7d792018-12-11 10:35:51 +0000670 MPI_VALIDATE_RET( X != NULL );
671 MPI_VALIDATE_RET( fin != NULL );
672
673 if( radix < 2 || radix > 16 )
674 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
675
Paul Bakker5121ce52009-01-03 21:22:43 +0000676 memset( s, 0, sizeof( s ) );
677 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000679
680 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000681 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000683
Hanno Beckerb2034b72017-04-26 11:46:46 +0100684 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
685 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000686
687 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100688 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000689 if( mpi_get_digit( &d, radix, *p ) != 0 )
690 break;
691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200692 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000693}
694
695/*
696 * Write X into an opened file (or stdout if fout == NULL)
697 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000699{
Paul Bakker23986e52011-04-24 08:57:21 +0000700 int ret;
701 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000702 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000703 * Buffer should have space for (short) label and decimal formatted MPI,
704 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000705 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000707 MPI_VALIDATE_RET( X != NULL );
708
709 if( radix < 2 || radix > 16 )
710 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100712 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000713
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100714 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000715
716 if( p == NULL ) p = "";
717
718 plen = strlen( p );
719 slen = strlen( s );
720 s[slen++] = '\r';
721 s[slen++] = '\n';
722
723 if( fout != NULL )
724 {
725 if( fwrite( p, 1, plen, fout ) != plen ||
726 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200727 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000728 }
729 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200730 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000731
732cleanup:
733
734 return( ret );
735}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200736#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000737
Hanno Beckerda1655a2017-10-18 14:21:44 +0100738
739/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
740 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000741
742static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
743{
744 uint8_t i;
Hanno Becker92c98932019-05-01 17:09:11 +0100745 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000746 mbedtls_mpi_uint tmp = 0;
Hanno Becker92c98932019-05-01 17:09:11 +0100747
748 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
749 {
750 tmp <<= CHAR_BIT;
751 tmp |= (mbedtls_mpi_uint) *x_ptr;
752 }
753
Hanno Beckerf8720072018-11-08 11:53:49 +0000754 return( tmp );
755}
756
757static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
758{
759#if defined(__BYTE_ORDER__)
760
761/* Nothing to do on bigendian systems. */
762#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
763 return( x );
764#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
765
766#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
767
768/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000769#if defined(__GNUC__) && defined(__GNUC_PREREQ)
770#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000771#define have_bswap
772#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000773#endif
774
775#if defined(__clang__) && defined(__has_builtin)
776#if __has_builtin(__builtin_bswap32) && \
777 __has_builtin(__builtin_bswap64)
778#define have_bswap
779#endif
780#endif
781
Hanno Beckerf8720072018-11-08 11:53:49 +0000782#if defined(have_bswap)
783 /* The compiler is hopefully able to statically evaluate this! */
784 switch( sizeof(mbedtls_mpi_uint) )
785 {
786 case 4:
787 return( __builtin_bswap32(x) );
788 case 8:
789 return( __builtin_bswap64(x) );
790 }
791#endif
792#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
793#endif /* __BYTE_ORDER__ */
794
795 /* Fall back to C-based reordering if we don't know the byte order
796 * or we couldn't use a compiler-specific builtin. */
797 return( mpi_uint_bigendian_to_host_c( x ) );
798}
799
Hanno Becker2be8a552018-10-25 12:40:09 +0100800static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100801{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100802 mbedtls_mpi_uint *cur_limb_left;
803 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100804 if( limbs == 0 )
805 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100806
807 /*
808 * Traverse limbs and
809 * - adapt byte-order in each limb
810 * - swap the limbs themselves.
811 * For that, simultaneously traverse the limbs from left to right
812 * and from right to left, as long as the left index is not bigger
813 * than the right index (it's not a problem if limbs is odd and the
814 * indices coincide in the last iteration).
815 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100816 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
817 cur_limb_left <= cur_limb_right;
818 cur_limb_left++, cur_limb_right-- )
819 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000820 mbedtls_mpi_uint tmp;
821 /* Note that if cur_limb_left == cur_limb_right,
822 * this code effectively swaps the bytes only once. */
823 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
824 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
825 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100826 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100827}
828
Paul Bakker5121ce52009-01-03 21:22:43 +0000829/*
830 * Import X from unsigned binary data, big endian
831 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200832int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000833{
Paul Bakker23986e52011-04-24 08:57:21 +0000834 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100835 size_t const limbs = CHARS_TO_LIMBS( buflen );
836 size_t const overhead = ( limbs * ciL ) - buflen;
837 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000838
Hanno Becker8ce11a32018-12-19 16:18:52 +0000839 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000840 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
841
Hanno Becker073c1992017-10-17 15:17:27 +0100842 /* Ensure that target MPI has exactly the necessary number of limbs */
843 if( X->n != limbs )
844 {
845 mbedtls_mpi_free( X );
846 mbedtls_mpi_init( X );
847 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
848 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200849 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000850
Hanno Becker0e810b92019-01-03 17:13:11 +0000851 /* Avoid calling `memcpy` with NULL source argument,
852 * even if buflen is 0. */
853 if( buf != NULL )
854 {
855 Xp = (unsigned char*) X->p;
856 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100857
Hanno Becker0e810b92019-01-03 17:13:11 +0000858 mpi_bigendian_to_host( X->p, limbs );
859 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000860
861cleanup:
862
863 return( ret );
864}
865
866/*
867 * Export X into unsigned binary data, big endian
868 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100869int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
870 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000871{
Hanno Becker73d7d792018-12-11 10:35:51 +0000872 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100873 size_t bytes_to_copy;
874 unsigned char *p;
875 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000876
Hanno Becker73d7d792018-12-11 10:35:51 +0000877 MPI_VALIDATE_RET( X != NULL );
878 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
879
880 stored_bytes = X->n * ciL;
881
Gilles Peskine11cdb052018-11-20 16:47:47 +0100882 if( stored_bytes < buflen )
883 {
884 /* There is enough space in the output buffer. Write initial
885 * null bytes and record the position at which to start
886 * writing the significant bytes. In this case, the execution
887 * trace of this function does not depend on the value of the
888 * number. */
889 bytes_to_copy = stored_bytes;
890 p = buf + buflen - stored_bytes;
891 memset( buf, 0, buflen - stored_bytes );
892 }
893 else
894 {
895 /* The output buffer is smaller than the allocated size of X.
896 * However X may fit if its leading bytes are zero. */
897 bytes_to_copy = buflen;
898 p = buf;
899 for( i = bytes_to_copy; i < stored_bytes; i++ )
900 {
901 if( GET_BYTE( X, i ) != 0 )
902 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
903 }
904 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000905
Gilles Peskine11cdb052018-11-20 16:47:47 +0100906 for( i = 0; i < bytes_to_copy; i++ )
907 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000908
909 return( 0 );
910}
911
912/*
913 * Left-shift: X <<= count
914 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200915int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000916{
Paul Bakker23986e52011-04-24 08:57:21 +0000917 int ret;
918 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000920 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000921
922 v0 = count / (biL );
923 t1 = count & (biL - 1);
924
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200925 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000926
Paul Bakkerf9688572011-05-05 10:00:45 +0000927 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200928 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000929
930 ret = 0;
931
932 /*
933 * shift by count / limb_size
934 */
935 if( v0 > 0 )
936 {
Paul Bakker23986e52011-04-24 08:57:21 +0000937 for( i = X->n; i > v0; i-- )
938 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000939
Paul Bakker23986e52011-04-24 08:57:21 +0000940 for( ; i > 0; i-- )
941 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000942 }
943
944 /*
945 * shift by count % limb_size
946 */
947 if( t1 > 0 )
948 {
949 for( i = v0; i < X->n; i++ )
950 {
951 r1 = X->p[i] >> (biL - t1);
952 X->p[i] <<= t1;
953 X->p[i] |= r0;
954 r0 = r1;
955 }
956 }
957
958cleanup:
959
960 return( ret );
961}
962
963/*
964 * Right-shift: X >>= count
965 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200966int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000967{
Paul Bakker23986e52011-04-24 08:57:21 +0000968 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200969 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000970 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000971
972 v0 = count / biL;
973 v1 = count & (biL - 1);
974
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100975 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200976 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100977
Paul Bakker5121ce52009-01-03 21:22:43 +0000978 /*
979 * shift by count / limb_size
980 */
981 if( v0 > 0 )
982 {
983 for( i = 0; i < X->n - v0; i++ )
984 X->p[i] = X->p[i + v0];
985
986 for( ; i < X->n; i++ )
987 X->p[i] = 0;
988 }
989
990 /*
991 * shift by count % limb_size
992 */
993 if( v1 > 0 )
994 {
Paul Bakker23986e52011-04-24 08:57:21 +0000995 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000996 {
Paul Bakker23986e52011-04-24 08:57:21 +0000997 r1 = X->p[i - 1] << (biL - v1);
998 X->p[i - 1] >>= v1;
999 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001000 r0 = r1;
1001 }
1002 }
1003
1004 return( 0 );
1005}
1006
1007/*
1008 * Compare unsigned values
1009 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001010int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001011{
Paul Bakker23986e52011-04-24 08:57:21 +00001012 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001013 MPI_VALIDATE_RET( X != NULL );
1014 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001015
Paul Bakker23986e52011-04-24 08:57:21 +00001016 for( i = X->n; i > 0; i-- )
1017 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001018 break;
1019
Paul Bakker23986e52011-04-24 08:57:21 +00001020 for( j = Y->n; j > 0; j-- )
1021 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001022 break;
1023
Paul Bakker23986e52011-04-24 08:57:21 +00001024 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001025 return( 0 );
1026
1027 if( i > j ) return( 1 );
1028 if( j > i ) return( -1 );
1029
Paul Bakker23986e52011-04-24 08:57:21 +00001030 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001031 {
Paul Bakker23986e52011-04-24 08:57:21 +00001032 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1033 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001034 }
1035
1036 return( 0 );
1037}
1038
1039/*
1040 * Compare signed values
1041 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001043{
Paul Bakker23986e52011-04-24 08:57:21 +00001044 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001045 MPI_VALIDATE_RET( X != NULL );
1046 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001047
Paul Bakker23986e52011-04-24 08:57:21 +00001048 for( i = X->n; i > 0; i-- )
1049 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001050 break;
1051
Paul Bakker23986e52011-04-24 08:57:21 +00001052 for( j = Y->n; j > 0; j-- )
1053 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001054 break;
1055
Paul Bakker23986e52011-04-24 08:57:21 +00001056 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001057 return( 0 );
1058
1059 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001060 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001061
1062 if( X->s > 0 && Y->s < 0 ) return( 1 );
1063 if( Y->s > 0 && X->s < 0 ) return( -1 );
1064
Paul Bakker23986e52011-04-24 08:57:21 +00001065 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001066 {
Paul Bakker23986e52011-04-24 08:57:21 +00001067 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1068 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001069 }
1070
1071 return( 0 );
1072}
1073
Janos Follath45ec9902019-10-14 09:09:32 +01001074/** Decide if an integer is less than the other, without branches.
1075 *
1076 * \param x First integer.
1077 * \param y Second integer.
1078 *
1079 * \return 1 if \p x is less than \p y, 0 otherwise
1080 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001081static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1082 const mbedtls_mpi_uint y )
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001083{
1084 mbedtls_mpi_uint ret;
1085 mbedtls_mpi_uint cond;
1086
1087 /*
1088 * Check if the most significant bits (MSB) of the operands are different.
1089 */
1090 cond = ( x ^ y );
1091 /*
1092 * If the MSB are the same then the difference x-y will be negative (and
1093 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1094 */
1095 ret = ( x - y ) & ~cond;
1096 /*
1097 * If the MSB are different, then the operand with the MSB of 1 is the
1098 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1099 * the MSB of y is 0.)
1100 */
1101 ret |= y & cond;
1102
1103
Janos Follath7a34bcf2019-10-14 08:59:14 +01001104 ret = ret >> ( biL - 1 );
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001105
1106 return ret;
1107}
1108
1109/*
1110 * Compare signed values in constant time
1111 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001112int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1113 unsigned *ret )
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001114{
1115 size_t i;
Janos Follathb11ce0e2019-10-14 09:01:15 +01001116 unsigned cond, done, sign_X, sign_Y;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001117
1118 MPI_VALIDATE_RET( X != NULL );
1119 MPI_VALIDATE_RET( Y != NULL );
1120 MPI_VALIDATE_RET( ret != NULL );
1121
1122 if( X->n != Y->n )
1123 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1124
1125 /*
Janos Follath58525182019-10-28 12:12:15 +00001126 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1127 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001128 */
Janos Follath58525182019-10-28 12:12:15 +00001129 sign_X = ( X->s & 2 ) >> 1;
1130 sign_Y = ( Y->s & 2 ) >> 1;
Janos Follath867a3ab2019-10-11 14:21:53 +01001131
1132 /*
1133 * If the signs are different, then the positive operand is the bigger.
1134 * That is if X is negative (sign bit 1), then X < Y is true and it is false
1135 * if X is positive (sign bit 0).
1136 */
1137 cond = ( sign_X ^ sign_Y );
1138 *ret = cond & sign_X;
1139
1140 /*
1141 * This is a constant time function, we might have the result, but we still
1142 * need to go through the loop. Record if we have the result already.
1143 */
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001144 done = cond;
1145
1146 for( i = X->n; i > 0; i-- )
1147 {
1148 /*
Janos Follath867a3ab2019-10-11 14:21:53 +01001149 * If Y->p[i - 1] < X->p[i - 1] and both X and Y are negative, then
1150 * X < Y.
1151 *
1152 * Again even if we can make a decision, we just mark the result and
1153 * the fact that we are done and continue looping.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001154 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001155 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] ) & sign_X;
1156 *ret |= cond & ( 1 - done );
Janos Follath4f6cf382019-10-11 10:43:40 +01001157 done |= cond & ( 1 - done );
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001158
1159 /*
Janos Follath867a3ab2019-10-11 14:21:53 +01001160 * If X->p[i - 1] < Y->p[i - 1] and both X and Y are positive, then
1161 * X < Y.
1162 *
1163 * Again even if we can make a decision, we just mark the result and
1164 * the fact that we are done and continue looping.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001165 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001166 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] ) & ( 1 - sign_X );
1167 *ret |= cond & ( 1 - done );
Janos Follath4f6cf382019-10-11 10:43:40 +01001168 done |= cond & ( 1 - done );
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001169 }
1170
1171 return( 0 );
1172}
1173
Paul Bakker5121ce52009-01-03 21:22:43 +00001174/*
1175 * Compare signed values
1176 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001177int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001178{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001179 mbedtls_mpi Y;
1180 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001181 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001182
1183 *p = ( z < 0 ) ? -z : z;
1184 Y.s = ( z < 0 ) ? -1 : 1;
1185 Y.n = 1;
1186 Y.p = p;
1187
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001188 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001189}
1190
1191/*
1192 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1193 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001194int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001195{
Paul Bakker23986e52011-04-24 08:57:21 +00001196 int ret;
1197 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001198 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001199 MPI_VALIDATE_RET( X != NULL );
1200 MPI_VALIDATE_RET( A != NULL );
1201 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001202
1203 if( X == B )
1204 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001205 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001206 }
1207
1208 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001209 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001210
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001211 /*
1212 * X should always be positive as a result of unsigned additions.
1213 */
1214 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001215
Paul Bakker23986e52011-04-24 08:57:21 +00001216 for( j = B->n; j > 0; j-- )
1217 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001218 break;
1219
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001220 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001221
1222 o = B->p; p = X->p; c = 0;
1223
Janos Follath6c922682015-10-30 17:43:11 +01001224 /*
1225 * tmp is used because it might happen that p == o
1226 */
Paul Bakker23986e52011-04-24 08:57:21 +00001227 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001228 {
Janos Follath6c922682015-10-30 17:43:11 +01001229 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001230 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001231 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001232 }
1233
1234 while( c != 0 )
1235 {
1236 if( i >= X->n )
1237 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001238 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001239 p = X->p + i;
1240 }
1241
Paul Bakker2d319fd2012-09-16 21:34:26 +00001242 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001243 }
1244
1245cleanup:
1246
1247 return( ret );
1248}
1249
1250/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001251 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001252 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001253static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001254{
Paul Bakker23986e52011-04-24 08:57:21 +00001255 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001256 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001257
1258 for( i = c = 0; i < n; i++, s++, d++ )
1259 {
1260 z = ( *d < c ); *d -= c;
1261 c = ( *d < *s ) + z; *d -= *s;
1262 }
1263
1264 while( c != 0 )
1265 {
1266 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001267 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001268 }
1269}
1270
1271/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001272 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001273 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001274int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001275{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001276 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001277 int ret;
1278 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001279 MPI_VALIDATE_RET( X != NULL );
1280 MPI_VALIDATE_RET( A != NULL );
1281 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001283 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1284 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001285
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001286 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001287
1288 if( X == B )
1289 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001290 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001291 B = &TB;
1292 }
1293
1294 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001295 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001296
Paul Bakker1ef7a532009-06-20 10:50:55 +00001297 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001298 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001299 */
1300 X->s = 1;
1301
Paul Bakker5121ce52009-01-03 21:22:43 +00001302 ret = 0;
1303
Paul Bakker23986e52011-04-24 08:57:21 +00001304 for( n = B->n; n > 0; n-- )
1305 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001306 break;
1307
Paul Bakker23986e52011-04-24 08:57:21 +00001308 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001309
1310cleanup:
1311
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001312 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001313
1314 return( ret );
1315}
1316
1317/*
1318 * Signed addition: X = A + B
1319 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001320int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001321{
Hanno Becker73d7d792018-12-11 10:35:51 +00001322 int ret, s;
1323 MPI_VALIDATE_RET( X != NULL );
1324 MPI_VALIDATE_RET( A != NULL );
1325 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001326
Hanno Becker73d7d792018-12-11 10:35:51 +00001327 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001328 if( A->s * B->s < 0 )
1329 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001330 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001331 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001333 X->s = s;
1334 }
1335 else
1336 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001337 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001338 X->s = -s;
1339 }
1340 }
1341 else
1342 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001343 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001344 X->s = s;
1345 }
1346
1347cleanup:
1348
1349 return( ret );
1350}
1351
1352/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001353 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001354 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001355int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001356{
Hanno Becker73d7d792018-12-11 10:35:51 +00001357 int ret, s;
1358 MPI_VALIDATE_RET( X != NULL );
1359 MPI_VALIDATE_RET( A != NULL );
1360 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001361
Hanno Becker73d7d792018-12-11 10:35:51 +00001362 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001363 if( A->s * B->s > 0 )
1364 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001366 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001367 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001368 X->s = s;
1369 }
1370 else
1371 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001373 X->s = -s;
1374 }
1375 }
1376 else
1377 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001378 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001379 X->s = s;
1380 }
1381
1382cleanup:
1383
1384 return( ret );
1385}
1386
1387/*
1388 * Signed addition: X = A + b
1389 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001391{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392 mbedtls_mpi _B;
1393 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001394 MPI_VALIDATE_RET( X != NULL );
1395 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001396
1397 p[0] = ( b < 0 ) ? -b : b;
1398 _B.s = ( b < 0 ) ? -1 : 1;
1399 _B.n = 1;
1400 _B.p = p;
1401
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001402 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001403}
1404
1405/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001406 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001407 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001408int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001409{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001410 mbedtls_mpi _B;
1411 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001412 MPI_VALIDATE_RET( X != NULL );
1413 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001414
1415 p[0] = ( b < 0 ) ? -b : b;
1416 _B.s = ( b < 0 ) ? -1 : 1;
1417 _B.n = 1;
1418 _B.p = p;
1419
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001420 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001421}
1422
1423/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001424 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001425 */
1426static
1427#if defined(__APPLE__) && defined(__arm__)
1428/*
1429 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1430 * appears to need this to prevent bad ARM code generation at -O3.
1431 */
1432__attribute__ ((noinline))
1433#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001434void 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 +00001435{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001436 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001437
1438#if defined(MULADDC_HUIT)
1439 for( ; i >= 8; i -= 8 )
1440 {
1441 MULADDC_INIT
1442 MULADDC_HUIT
1443 MULADDC_STOP
1444 }
1445
1446 for( ; i > 0; i-- )
1447 {
1448 MULADDC_INIT
1449 MULADDC_CORE
1450 MULADDC_STOP
1451 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001452#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001453 for( ; i >= 16; i -= 16 )
1454 {
1455 MULADDC_INIT
1456 MULADDC_CORE MULADDC_CORE
1457 MULADDC_CORE MULADDC_CORE
1458 MULADDC_CORE MULADDC_CORE
1459 MULADDC_CORE MULADDC_CORE
1460
1461 MULADDC_CORE MULADDC_CORE
1462 MULADDC_CORE MULADDC_CORE
1463 MULADDC_CORE MULADDC_CORE
1464 MULADDC_CORE MULADDC_CORE
1465 MULADDC_STOP
1466 }
1467
1468 for( ; i >= 8; i -= 8 )
1469 {
1470 MULADDC_INIT
1471 MULADDC_CORE MULADDC_CORE
1472 MULADDC_CORE MULADDC_CORE
1473
1474 MULADDC_CORE MULADDC_CORE
1475 MULADDC_CORE MULADDC_CORE
1476 MULADDC_STOP
1477 }
1478
1479 for( ; i > 0; i-- )
1480 {
1481 MULADDC_INIT
1482 MULADDC_CORE
1483 MULADDC_STOP
1484 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001485#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001486
1487 t++;
1488
1489 do {
1490 *d += c; c = ( *d < c ); d++;
1491 }
1492 while( c != 0 );
1493}
1494
1495/*
1496 * Baseline multiplication: X = A * B (HAC 14.12)
1497 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001498int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001499{
Paul Bakker23986e52011-04-24 08:57:21 +00001500 int ret;
1501 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001502 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001503 MPI_VALIDATE_RET( X != NULL );
1504 MPI_VALIDATE_RET( A != NULL );
1505 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001507 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001509 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1510 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001511
Paul Bakker23986e52011-04-24 08:57:21 +00001512 for( i = A->n; i > 0; i-- )
1513 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001514 break;
1515
Paul Bakker23986e52011-04-24 08:57:21 +00001516 for( j = B->n; j > 0; j-- )
1517 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001518 break;
1519
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001520 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1521 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001522
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001523 for( ; j > 0; j-- )
1524 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001525
1526 X->s = A->s * B->s;
1527
1528cleanup:
1529
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001530 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001531
1532 return( ret );
1533}
1534
1535/*
1536 * Baseline multiplication: X = A * b
1537 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001538int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001539{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001540 mbedtls_mpi _B;
1541 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001542 MPI_VALIDATE_RET( X != NULL );
1543 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001544
1545 _B.s = 1;
1546 _B.n = 1;
1547 _B.p = p;
1548 p[0] = b;
1549
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001550 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001551}
1552
1553/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001554 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1555 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001556 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001557static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1558 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001559{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001560#if defined(MBEDTLS_HAVE_UDBL)
1561 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001562#else
Simon Butcher9803d072016-01-03 00:24:34 +00001563 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1564 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001565 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1566 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001567 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001568#endif
1569
Simon Butcher15b15d12015-11-26 19:35:03 +00001570 /*
1571 * Check for overflow
1572 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001573 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001574 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001575 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001576
Simon Butcherf5ba0452015-12-27 23:01:55 +00001577 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001578 }
1579
1580#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001581 dividend = (mbedtls_t_udbl) u1 << biL;
1582 dividend |= (mbedtls_t_udbl) u0;
1583 quotient = dividend / d;
1584 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1585 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1586
1587 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001588 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001589
1590 return (mbedtls_mpi_uint) quotient;
1591#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001592
1593 /*
1594 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1595 * Vol. 2 - Seminumerical Algorithms, Knuth
1596 */
1597
1598 /*
1599 * Normalize the divisor, d, and dividend, u0, u1
1600 */
1601 s = mbedtls_clz( d );
1602 d = d << s;
1603
1604 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001605 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001606 u0 = u0 << s;
1607
1608 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001609 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001610
1611 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001612 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001613
1614 /*
1615 * Find the first quotient and remainder
1616 */
1617 q1 = u1 / d1;
1618 r0 = u1 - d1 * q1;
1619
1620 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1621 {
1622 q1 -= 1;
1623 r0 += d1;
1624
1625 if ( r0 >= radix ) break;
1626 }
1627
Simon Butcherf5ba0452015-12-27 23:01:55 +00001628 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001629 q0 = rAX / d1;
1630 r0 = rAX - q0 * d1;
1631
1632 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1633 {
1634 q0 -= 1;
1635 r0 += d1;
1636
1637 if ( r0 >= radix ) break;
1638 }
1639
1640 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001641 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001642
1643 quotient = q1 * radix + q0;
1644
1645 return quotient;
1646#endif
1647}
1648
1649/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001650 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001651 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001652int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1653 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001654{
Paul Bakker23986e52011-04-24 08:57:21 +00001655 int ret;
1656 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001657 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001658 MPI_VALIDATE_RET( A != NULL );
1659 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1662 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001663
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001664 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1665 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001666
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001667 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001668 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001669 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1670 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001671 return( 0 );
1672 }
1673
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001674 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1675 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001676 X.s = Y.s = 1;
1677
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001678 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1679 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1680 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1681 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001682
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001683 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001684 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001685 {
1686 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001687 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1688 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001689 }
1690 else k = 0;
1691
1692 n = X.n - 1;
1693 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001694 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001695
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001696 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001697 {
1698 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001699 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001700 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001701 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001702
1703 for( i = n; i > t ; i-- )
1704 {
1705 if( X.p[i] >= Y.p[t] )
1706 Z.p[i - t - 1] = ~0;
1707 else
1708 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001709 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1710 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001711 }
1712
1713 Z.p[i - t - 1]++;
1714 do
1715 {
1716 Z.p[i - t - 1]--;
1717
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001718 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001719 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001720 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001721 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001722
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001723 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001724 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1725 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001726 T2.p[2] = X.p[i];
1727 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001728 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001729
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001730 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1731 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1732 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001733
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001734 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001735 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001736 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1737 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1738 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001739 Z.p[i - t - 1]--;
1740 }
1741 }
1742
1743 if( Q != NULL )
1744 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001745 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001746 Q->s = A->s * B->s;
1747 }
1748
1749 if( R != NULL )
1750 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001751 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001752 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001753 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001754
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001756 R->s = 1;
1757 }
1758
1759cleanup:
1760
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001761 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1762 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001763
1764 return( ret );
1765}
1766
1767/*
1768 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001769 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001770int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1771 const mbedtls_mpi *A,
1772 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001773{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001774 mbedtls_mpi _B;
1775 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001776 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001777
1778 p[0] = ( b < 0 ) ? -b : b;
1779 _B.s = ( b < 0 ) ? -1 : 1;
1780 _B.n = 1;
1781 _B.p = p;
1782
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001783 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001784}
1785
1786/*
1787 * Modulo: R = A mod B
1788 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001789int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001790{
1791 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001792 MPI_VALIDATE_RET( R != NULL );
1793 MPI_VALIDATE_RET( A != NULL );
1794 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001795
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001796 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1797 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001798
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001799 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001800
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001801 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1802 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001803
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001804 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1805 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001806
1807cleanup:
1808
1809 return( ret );
1810}
1811
1812/*
1813 * Modulo: r = A mod b
1814 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001815int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001816{
Paul Bakker23986e52011-04-24 08:57:21 +00001817 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001818 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001819 MPI_VALIDATE_RET( r != NULL );
1820 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001821
1822 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001823 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001824
1825 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001826 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001827
1828 /*
1829 * handle trivial cases
1830 */
1831 if( b == 1 )
1832 {
1833 *r = 0;
1834 return( 0 );
1835 }
1836
1837 if( b == 2 )
1838 {
1839 *r = A->p[0] & 1;
1840 return( 0 );
1841 }
1842
1843 /*
1844 * general case
1845 */
Paul Bakker23986e52011-04-24 08:57:21 +00001846 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001847 {
Paul Bakker23986e52011-04-24 08:57:21 +00001848 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001849 y = ( y << biH ) | ( x >> biH );
1850 z = y / b;
1851 y -= z * b;
1852
1853 x <<= biH;
1854 y = ( y << biH ) | ( x >> biH );
1855 z = y / b;
1856 y -= z * b;
1857 }
1858
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001859 /*
1860 * If A is negative, then the current y represents a negative value.
1861 * Flipping it to the positive side.
1862 */
1863 if( A->s < 0 && y != 0 )
1864 y = b - y;
1865
Paul Bakker5121ce52009-01-03 21:22:43 +00001866 *r = y;
1867
1868 return( 0 );
1869}
1870
1871/*
1872 * Fast Montgomery initialization (thanks to Tom St Denis)
1873 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001874static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001875{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001876 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001877 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001878
1879 x = m0;
1880 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001881
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001882 for( i = biL; i >= 8; i /= 2 )
1883 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001884
1885 *mm = ~x + 1;
1886}
1887
1888/*
1889 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1890 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001891static 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 +02001892 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001893{
Paul Bakker23986e52011-04-24 08:57:21 +00001894 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001895 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001896
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001897 if( T->n < N->n + 1 || T->p == NULL )
1898 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1899
Paul Bakker5121ce52009-01-03 21:22:43 +00001900 memset( T->p, 0, T->n * ciL );
1901
1902 d = T->p;
1903 n = N->n;
1904 m = ( B->n < n ) ? B->n : n;
1905
1906 for( i = 0; i < n; i++ )
1907 {
1908 /*
1909 * T = (T + u0*B + u1*N) / 2^biL
1910 */
1911 u0 = A->p[i];
1912 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1913
1914 mpi_mul_hlp( m, B->p, d, u0 );
1915 mpi_mul_hlp( n, N->p, d, u1 );
1916
1917 *d++ = u0; d[n + 1] = 0;
1918 }
1919
Paul Bakker66d5d072014-06-17 16:39:18 +02001920 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001921
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001922 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001923 mpi_sub_hlp( n, N->p, A->p );
1924 else
1925 /* prevent timing attacks */
1926 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001927
1928 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001929}
1930
1931/*
1932 * Montgomery reduction: A = A * R^-1 mod N
1933 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001934static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1935 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001936{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001937 mbedtls_mpi_uint z = 1;
1938 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001939
Paul Bakker8ddb6452013-02-27 14:56:33 +01001940 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001941 U.p = &z;
1942
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001943 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001944}
1945
1946/*
1947 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1948 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001949int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1950 const mbedtls_mpi *E, const mbedtls_mpi *N,
1951 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001952{
Paul Bakker23986e52011-04-24 08:57:21 +00001953 int ret;
1954 size_t wbits, wsize, one = 1;
1955 size_t i, j, nblimbs;
1956 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001957 mbedtls_mpi_uint ei, mm, state;
1958 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001959 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001960
Hanno Becker73d7d792018-12-11 10:35:51 +00001961 MPI_VALIDATE_RET( X != NULL );
1962 MPI_VALIDATE_RET( A != NULL );
1963 MPI_VALIDATE_RET( E != NULL );
1964 MPI_VALIDATE_RET( N != NULL );
1965
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001966 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001967 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001968
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001969 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1970 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001971
1972 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001973 * Init temps and window size
1974 */
1975 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001976 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1977 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001978 memset( W, 0, sizeof( W ) );
1979
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001980 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001981
1982 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1983 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1984
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001985#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001986 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1987 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001988#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001989
Paul Bakker5121ce52009-01-03 21:22:43 +00001990 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001991 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1992 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1993 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001994
1995 /*
Paul Bakker50546922012-05-19 08:40:49 +00001996 * Compensate for negative A (and correct at the end)
1997 */
1998 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001999 if( neg )
2000 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002001 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002002 Apos.s = 1;
2003 A = &Apos;
2004 }
2005
2006 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002007 * If 1st call, pre-compute R^2 mod N
2008 */
2009 if( _RR == NULL || _RR->p == NULL )
2010 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002011 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2012 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2013 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002014
2015 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002017 }
2018 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002019 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002020
2021 /*
2022 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2023 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002024 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2025 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002026 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002027 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002028
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002029 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002030
2031 /*
2032 * X = R^2 * R^-1 mod N = R mod N
2033 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002035 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002036
2037 if( wsize > 1 )
2038 {
2039 /*
2040 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2041 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002042 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002044 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2045 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002046
2047 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002048 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002049
Paul Bakker5121ce52009-01-03 21:22:43 +00002050 /*
2051 * W[i] = W[i - 1] * W[1]
2052 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002053 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002054 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002055 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2056 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002057
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002058 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002059 }
2060 }
2061
2062 nblimbs = E->n;
2063 bufsize = 0;
2064 nbits = 0;
2065 wbits = 0;
2066 state = 0;
2067
2068 while( 1 )
2069 {
2070 if( bufsize == 0 )
2071 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002072 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002073 break;
2074
Paul Bakker0d7702c2013-10-29 16:18:35 +01002075 nblimbs--;
2076
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002077 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002078 }
2079
2080 bufsize--;
2081
2082 ei = (E->p[nblimbs] >> bufsize) & 1;
2083
2084 /*
2085 * skip leading 0s
2086 */
2087 if( ei == 0 && state == 0 )
2088 continue;
2089
2090 if( ei == 0 && state == 1 )
2091 {
2092 /*
2093 * out of window, square X
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 continue;
2097 }
2098
2099 /*
2100 * add ei to current window
2101 */
2102 state = 2;
2103
2104 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002105 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002106
2107 if( nbits == wsize )
2108 {
2109 /*
2110 * X = X^wsize R^-1 mod N
2111 */
2112 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002113 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002114
2115 /*
2116 * X = X * W[wbits] R^-1 mod N
2117 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002118 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002119
2120 state--;
2121 nbits = 0;
2122 wbits = 0;
2123 }
2124 }
2125
2126 /*
2127 * process the remaining bits
2128 */
2129 for( i = 0; i < nbits; i++ )
2130 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002131 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002132
2133 wbits <<= 1;
2134
Paul Bakker66d5d072014-06-17 16:39:18 +02002135 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002136 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002137 }
2138
2139 /*
2140 * X = A^E * R * R^-1 mod N = A^E mod N
2141 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002142 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002143
Hanno Beckera4af1c42017-04-18 09:07:45 +01002144 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002145 {
2146 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002147 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002148 }
2149
Paul Bakker5121ce52009-01-03 21:22:43 +00002150cleanup:
2151
Paul Bakker66d5d072014-06-17 16:39:18 +02002152 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002153 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002154
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002155 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002156
Paul Bakker75a28602014-03-31 12:08:17 +02002157 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002158 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002159
2160 return( ret );
2161}
2162
Paul Bakker5121ce52009-01-03 21:22:43 +00002163/*
2164 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2165 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002166int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002167{
Paul Bakker23986e52011-04-24 08:57:21 +00002168 int ret;
2169 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002170 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002171
Hanno Becker73d7d792018-12-11 10:35:51 +00002172 MPI_VALIDATE_RET( G != NULL );
2173 MPI_VALIDATE_RET( A != NULL );
2174 MPI_VALIDATE_RET( B != NULL );
2175
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002176 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002177
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002178 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2179 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002181 lz = mbedtls_mpi_lsb( &TA );
2182 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002183
Paul Bakker66d5d072014-06-17 16:39:18 +02002184 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002185 lz = lzt;
2186
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002187 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2188 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002189
Paul Bakker5121ce52009-01-03 21:22:43 +00002190 TA.s = TB.s = 1;
2191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002192 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002193 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002194 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2195 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002196
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002197 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002198 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002199 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2200 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002201 }
2202 else
2203 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002204 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2205 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002206 }
2207 }
2208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002209 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2210 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002211
2212cleanup:
2213
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002214 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002215
2216 return( ret );
2217}
2218
Paul Bakker33dc46b2014-04-30 16:11:39 +02002219/*
2220 * Fill X with size bytes of random.
2221 *
2222 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002223 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002224 * deterministic, eg for tests).
2225 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002226int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002227 int (*f_rng)(void *, unsigned char *, size_t),
2228 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002229{
Paul Bakker23986e52011-04-24 08:57:21 +00002230 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002231 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002232 size_t const overhead = ( limbs * ciL ) - size;
2233 unsigned char *Xp;
2234
Hanno Becker8ce11a32018-12-19 16:18:52 +00002235 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002236 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002237
Hanno Beckerda1655a2017-10-18 14:21:44 +01002238 /* Ensure that target MPI has exactly the necessary number of limbs */
2239 if( X->n != limbs )
2240 {
2241 mbedtls_mpi_free( X );
2242 mbedtls_mpi_init( X );
2243 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2244 }
2245 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002246
Hanno Beckerda1655a2017-10-18 14:21:44 +01002247 Xp = (unsigned char*) X->p;
2248 f_rng( p_rng, Xp + overhead, size );
2249
Hanno Becker2be8a552018-10-25 12:40:09 +01002250 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002251
2252cleanup:
2253 return( ret );
2254}
2255
Paul Bakker5121ce52009-01-03 21:22:43 +00002256/*
2257 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2258 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002259int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002260{
2261 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002262 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002263 MPI_VALIDATE_RET( X != NULL );
2264 MPI_VALIDATE_RET( A != NULL );
2265 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002266
Hanno Becker4bcb4912017-04-18 15:49:39 +01002267 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002268 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002269
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002270 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2271 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2272 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002273
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002274 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002275
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002276 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002277 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002278 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002279 goto cleanup;
2280 }
2281
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002282 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2283 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2284 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2285 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002287 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2288 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2289 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2290 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002291
2292 do
2293 {
2294 while( ( TU.p[0] & 1 ) == 0 )
2295 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002296 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002297
2298 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2299 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002300 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2301 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002302 }
2303
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002304 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2305 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002306 }
2307
2308 while( ( TV.p[0] & 1 ) == 0 )
2309 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002310 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002311
2312 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2313 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002314 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2315 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002316 }
2317
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002318 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2319 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002320 }
2321
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002322 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002323 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002324 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2325 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2326 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002327 }
2328 else
2329 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2331 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2332 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002333 }
2334 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002336
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002337 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2338 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002340 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2341 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002343 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002344
2345cleanup:
2346
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2348 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2349 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002350
2351 return( ret );
2352}
2353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002354#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002355
Paul Bakker5121ce52009-01-03 21:22:43 +00002356static const int small_prime[] =
2357{
2358 3, 5, 7, 11, 13, 17, 19, 23,
2359 29, 31, 37, 41, 43, 47, 53, 59,
2360 61, 67, 71, 73, 79, 83, 89, 97,
2361 101, 103, 107, 109, 113, 127, 131, 137,
2362 139, 149, 151, 157, 163, 167, 173, 179,
2363 181, 191, 193, 197, 199, 211, 223, 227,
2364 229, 233, 239, 241, 251, 257, 263, 269,
2365 271, 277, 281, 283, 293, 307, 311, 313,
2366 317, 331, 337, 347, 349, 353, 359, 367,
2367 373, 379, 383, 389, 397, 401, 409, 419,
2368 421, 431, 433, 439, 443, 449, 457, 461,
2369 463, 467, 479, 487, 491, 499, 503, 509,
2370 521, 523, 541, 547, 557, 563, 569, 571,
2371 577, 587, 593, 599, 601, 607, 613, 617,
2372 619, 631, 641, 643, 647, 653, 659, 661,
2373 673, 677, 683, 691, 701, 709, 719, 727,
2374 733, 739, 743, 751, 757, 761, 769, 773,
2375 787, 797, 809, 811, 821, 823, 827, 829,
2376 839, 853, 857, 859, 863, 877, 881, 883,
2377 887, 907, 911, 919, 929, 937, 941, 947,
2378 953, 967, 971, 977, 983, 991, 997, -103
2379};
2380
2381/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002382 * Small divisors test (X must be positive)
2383 *
2384 * Return values:
2385 * 0: no small factor (possible prime, more tests needed)
2386 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002387 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002388 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002389 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002390static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002391{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002392 int ret = 0;
2393 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002394 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002395
Paul Bakker5121ce52009-01-03 21:22:43 +00002396 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002397 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002398
2399 for( i = 0; small_prime[i] > 0; i++ )
2400 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002401 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002402 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002403
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002404 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002405
2406 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002407 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002408 }
2409
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002410cleanup:
2411 return( ret );
2412}
2413
2414/*
2415 * Miller-Rabin pseudo-primality test (HAC 4.24)
2416 */
Janos Follathda31fa12018-09-03 14:45:23 +01002417static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002418 int (*f_rng)(void *, unsigned char *, size_t),
2419 void *p_rng )
2420{
Pascal Junodb99183d2015-03-11 16:49:45 +01002421 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002422 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002423 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002424
Hanno Becker8ce11a32018-12-19 16:18:52 +00002425 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002426 MPI_VALIDATE_RET( f_rng != NULL );
2427
2428 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2429 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002430 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002431
Paul Bakker5121ce52009-01-03 21:22:43 +00002432 /*
2433 * W = |X| - 1
2434 * R = W >> lsb( W )
2435 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002436 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2437 s = mbedtls_mpi_lsb( &W );
2438 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2439 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002440
Janos Follathda31fa12018-09-03 14:45:23 +01002441 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002442 {
2443 /*
2444 * pick a random A, 1 < A < |X| - 1
2445 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002446 count = 0;
2447 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002448 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002449
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002450 j = mbedtls_mpi_bitlen( &A );
2451 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002452 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002453 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002454 }
2455
2456 if (count++ > 30) {
Jens Wiklanderdfd447e2019-01-17 13:30:57 +01002457 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2458 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002459 }
2460
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002461 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2462 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002463
2464 /*
2465 * A = A^R mod |X|
2466 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002467 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002468
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002469 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2470 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002471 continue;
2472
2473 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002474 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002475 {
2476 /*
2477 * A = A * A mod |X|
2478 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002479 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2480 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002482 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002483 break;
2484
2485 j++;
2486 }
2487
2488 /*
2489 * not prime if A != |X| - 1 or A == 1
2490 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002491 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2492 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002493 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002494 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002495 break;
2496 }
2497 }
2498
2499cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002500 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2501 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002502 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002503
2504 return( ret );
2505}
2506
2507/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002508 * Pseudo-primality test: small factors, then Miller-Rabin
2509 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002510int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2511 int (*f_rng)(void *, unsigned char *, size_t),
2512 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002513{
2514 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002515 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002516 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002517 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002518
2519 XX.s = 1;
2520 XX.n = X->n;
2521 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002522
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002523 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2524 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2525 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002526
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002527 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002528 return( 0 );
2529
2530 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2531 {
2532 if( ret == 1 )
2533 return( 0 );
2534
2535 return( ret );
2536 }
2537
Janos Follathda31fa12018-09-03 14:45:23 +01002538 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002539}
2540
Janos Follatha0b67c22018-09-18 14:48:23 +01002541#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002542/*
2543 * Pseudo-primality test, error probability 2^-80
2544 */
2545int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2546 int (*f_rng)(void *, unsigned char *, size_t),
2547 void *p_rng )
2548{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002549 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002550 MPI_VALIDATE_RET( f_rng != NULL );
2551
Janos Follatha0b67c22018-09-18 14:48:23 +01002552 /*
2553 * In the past our key generation aimed for an error rate of at most
2554 * 2^-80. Since this function is deprecated, aim for the same certainty
2555 * here as well.
2556 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002557 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002558}
Janos Follatha0b67c22018-09-18 14:48:23 +01002559#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002560
2561/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002562 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002563 *
Janos Follathf301d232018-08-14 13:34:01 +01002564 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2565 * be either 1024 bits or 1536 bits long, and flags must contain
2566 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002567 */
Janos Follath7c025a92018-08-14 11:08:41 +01002568int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002569 int (*f_rng)(void *, unsigned char *, size_t),
2570 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002571{
Jethro Beekman66689272018-02-14 19:24:10 -08002572#ifdef MBEDTLS_HAVE_INT64
2573// ceil(2^63.5)
2574#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2575#else
2576// ceil(2^31.5)
2577#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2578#endif
2579 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002580 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002581 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002582 mbedtls_mpi_uint r;
2583 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002584
Hanno Becker8ce11a32018-12-19 16:18:52 +00002585 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002586 MPI_VALIDATE_RET( f_rng != NULL );
2587
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002588 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2589 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002591 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002592
2593 n = BITS_TO_LIMBS( nbits );
2594
Janos Follathda31fa12018-09-03 14:45:23 +01002595 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2596 {
2597 /*
2598 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2599 */
2600 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2601 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2602 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2603 }
2604 else
2605 {
2606 /*
2607 * 2^-100 error probability, number of rounds computed based on HAC,
2608 * fact 4.48
2609 */
2610 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2611 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2612 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2613 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2614 }
2615
Jethro Beekman66689272018-02-14 19:24:10 -08002616 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002617 {
Jethro Beekman66689272018-02-14 19:24:10 -08002618 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2619 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2620 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2621
2622 k = n * biL;
2623 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2624 X->p[0] |= 1;
2625
Janos Follath7c025a92018-08-14 11:08:41 +01002626 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002627 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002628 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002629
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002630 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002631 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002632 }
Jethro Beekman66689272018-02-14 19:24:10 -08002633 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002634 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002635 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002636 * An necessary condition for Y and X = 2Y + 1 to be prime
2637 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2638 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002639 */
Jethro Beekman66689272018-02-14 19:24:10 -08002640
2641 X->p[0] |= 2;
2642
2643 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2644 if( r == 0 )
2645 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2646 else if( r == 1 )
2647 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2648
2649 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2650 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2651 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2652
2653 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002654 {
Jethro Beekman66689272018-02-14 19:24:10 -08002655 /*
2656 * First, check small factors for X and Y
2657 * before doing Miller-Rabin on any of them
2658 */
2659 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2660 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002661 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002662 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002663 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002664 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002665 goto cleanup;
2666
2667 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2668 goto cleanup;
2669
2670 /*
2671 * Next candidates. We want to preserve Y = (X-1) / 2 and
2672 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2673 * so up Y by 6 and X by 12.
2674 */
2675 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2676 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002677 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002678 }
2679 }
2680
2681cleanup:
2682
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002683 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002684
2685 return( ret );
2686}
2687
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002688#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002689
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002690#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002691
Paul Bakker23986e52011-04-24 08:57:21 +00002692#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002693
2694static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2695{
2696 { 693, 609, 21 },
2697 { 1764, 868, 28 },
2698 { 768454923, 542167814, 1 }
2699};
2700
Paul Bakker5121ce52009-01-03 21:22:43 +00002701/*
2702 * Checkup routine
2703 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002704int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002705{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002706 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002707 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002708
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002709 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2710 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002711
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002712 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002713 "EFE021C2645FD1DC586E69184AF4A31E" \
2714 "D5F53E93B5F123FA41680867BA110131" \
2715 "944FE7952E2517337780CB0DB80E61AA" \
2716 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2717
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002718 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002719 "B2E7EFD37075B9F03FF989C7C5051C20" \
2720 "34D2A323810251127E7BF8625A4F49A5" \
2721 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2722 "5B5C25763222FEFCCFC38B832366C29E" ) );
2723
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002724 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002725 "0066A198186C18C10B2F5ED9B522752A" \
2726 "9830B69916E535C8F047518A889A43A5" \
2727 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2728
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002729 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002730
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002731 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002732 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2733 "9E857EA95A03512E2BAE7391688D264A" \
2734 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2735 "8001B72E848A38CAE1C65F78E56ABDEF" \
2736 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2737 "ECF677152EF804370C1A305CAF3B5BF1" \
2738 "30879B56C61DE584A0F53A2447A51E" ) );
2739
2740 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002741 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002742
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002743 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002744 {
2745 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002746 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002747
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002748 ret = 1;
2749 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002750 }
2751
2752 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002753 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002754
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002755 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002756
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002757 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002758 "256567336059E52CAE22925474705F39A94" ) );
2759
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002760 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002761 "6613F26162223DF488E9CD48CC132C7A" \
2762 "0AC93C701B001B092E4E5B9F73BCD27B" \
2763 "9EE50D0657C77F374E903CDFA4C642" ) );
2764
2765 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002766 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002767
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002768 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2769 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002770 {
2771 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002772 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002773
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002774 ret = 1;
2775 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002776 }
2777
2778 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002779 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002780
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002781 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002782
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002783 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002784 "36E139AEA55215609D2816998ED020BB" \
2785 "BD96C37890F65171D948E9BC7CBAA4D9" \
2786 "325D24D6A3C12710F10A09FA08AB87" ) );
2787
2788 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002789 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002790
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002791 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002792 {
2793 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002794 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002795
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002796 ret = 1;
2797 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002798 }
2799
2800 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002801 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002802
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002803 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002804
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002805 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002806 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2807 "C3DBA76456363A10869622EAC2DD84EC" \
2808 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2809
2810 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002811 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002812
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002813 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002814 {
2815 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002816 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002817
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002818 ret = 1;
2819 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002820 }
2821
2822 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002823 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002824
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002825 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002826 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002827
Paul Bakker66d5d072014-06-17 16:39:18 +02002828 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002829 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002830 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2831 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002832
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002833 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002834
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002835 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002836 {
2837 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002838 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002839
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002840 ret = 1;
2841 goto cleanup;
2842 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002843 }
2844
2845 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002846 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002847
Paul Bakker5121ce52009-01-03 21:22:43 +00002848cleanup:
2849
2850 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002851 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002852
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002853 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2854 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002855
2856 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002857 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002858
2859 return( ret );
2860}
2861
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002862#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002863
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002864#endif /* MBEDTLS_BIGNUM_C */