blob: 9af17aabd4eb2c31da2110a005b945acb4d82389 [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"
Janos Follath24eed8d2019-11-22 13:21:35 +000049#include "mbedtls/error.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000050
Rich Evans00ab4702015-02-06 13:43:58 +000051#include <string.h>
52
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020053#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000054#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020055#else
Rich Evans00ab4702015-02-06 13:43:58 +000056#include <stdio.h>
57#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020059#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020060#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020061#endif
62
Hanno Becker73d7d792018-12-11 10:35:51 +000063#define MPI_VALIDATE_RET( cond ) \
64 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
65#define MPI_VALIDATE( cond ) \
66 MBEDTLS_INTERNAL_VALIDATE( cond )
67
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020068#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000069#define biL (ciL << 3) /* bits in limb */
70#define biH (ciL << 2) /* half limb size */
71
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010072#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
73
Paul Bakker5121ce52009-01-03 21:22:43 +000074/*
75 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020076 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000077 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020078#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
79#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000080
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050081/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050082static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
83{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050084 mbedtls_platform_zeroize( v, ciL * n );
85}
86
Paul Bakker5121ce52009-01-03 21:22:43 +000087/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000088 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000089 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020090void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000091{
Hanno Becker73d7d792018-12-11 10:35:51 +000092 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000093
Paul Bakker6c591fa2011-05-05 11:49:20 +000094 X->s = 1;
95 X->n = 0;
96 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000097}
98
99/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000100 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000101 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200102void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000103{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000104 if( X == NULL )
105 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000106
Paul Bakker6c591fa2011-05-05 11:49:20 +0000107 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000108 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200109 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200110 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000111 }
112
Paul Bakker6c591fa2011-05-05 11:49:20 +0000113 X->s = 1;
114 X->n = 0;
115 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000116}
117
118/*
119 * Enlarge to the specified number of limbs
120 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000122{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200123 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000124 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000125
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200126 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200127 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000128
Paul Bakker5121ce52009-01-03 21:22:43 +0000129 if( X->n < nblimbs )
130 {
Simon Butcher29176892016-05-20 00:19:09 +0100131 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200132 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000133
Paul Bakker5121ce52009-01-03 21:22:43 +0000134 if( X->p != NULL )
135 {
136 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200137 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200138 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000139 }
140
141 X->n = nblimbs;
142 X->p = p;
143 }
144
145 return( 0 );
146}
147
148/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100149 * Resize down as much as possible,
150 * while keeping at least the specified number of limbs
151 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200152int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100153{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100155 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000156 MPI_VALIDATE_RET( X != NULL );
157
158 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
159 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100160
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100161 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100162 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200163 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine322752b2020-01-21 13:59:51 +0100164 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100165
166 for( i = X->n - 1; i > 0; i-- )
167 if( X->p[i] != 0 )
168 break;
169 i++;
170
171 if( i < nblimbs )
172 i = nblimbs;
173
Simon Butcher29176892016-05-20 00:19:09 +0100174 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200175 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100176
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100177 if( X->p != NULL )
178 {
179 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200180 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100182 }
183
184 X->n = i;
185 X->p = p;
186
187 return( 0 );
188}
189
190/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000191 * Copy the contents of Y into X
192 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200193int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000194{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100195 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000196 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000197 MPI_VALIDATE_RET( X != NULL );
198 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000199
200 if( X == Y )
201 return( 0 );
202
Gilles Peskinedb420622020-01-20 21:12:50 +0100203 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200204 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200206 return( 0 );
207 }
208
Paul Bakker5121ce52009-01-03 21:22:43 +0000209 for( i = Y->n - 1; i > 0; i-- )
210 if( Y->p[i] != 0 )
211 break;
212 i++;
213
214 X->s = Y->s;
215
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100216 if( X->n < i )
217 {
218 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
219 }
220 else
221 {
222 memset( X->p + i, 0, ( X->n - i ) * ciL );
223 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000224
Paul Bakker5121ce52009-01-03 21:22:43 +0000225 memcpy( X->p, Y->p, i * ciL );
226
227cleanup:
228
229 return( ret );
230}
231
232/*
233 * Swap the contents of X and Y
234 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000236{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200237 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000238 MPI_VALIDATE( X != NULL );
239 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241 memcpy( &T, X, sizeof( mbedtls_mpi ) );
242 memcpy( X, Y, sizeof( mbedtls_mpi ) );
243 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000244}
245
246/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100247 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100248 * about whether the assignment was made or not.
249 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200251int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100252{
253 int ret = 0;
254 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000255 MPI_VALIDATE_RET( X != NULL );
256 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100257
Pascal Junodb99183d2015-03-11 16:49:45 +0100258 /* make sure assign is 0 or 1 in a time-constant manner */
259 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100260
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100262
Paul Bakker66d5d072014-06-17 16:39:18 +0200263 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100264
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100265 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200266 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100267
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100268 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200269 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100270
271cleanup:
272 return( ret );
273}
274
275/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100276 * Conditionally swap X and Y, without leaking information
277 * about whether the swap was made or not.
278 * Here it is not ok to simply swap the pointers, which whould lead to
279 * different memory access patterns when X and Y are used afterwards.
280 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100282{
283 int ret, s;
284 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200285 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000286 MPI_VALIDATE_RET( X != NULL );
287 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100288
289 if( X == Y )
290 return( 0 );
291
Pascal Junodb99183d2015-03-11 16:49:45 +0100292 /* make sure swap is 0 or 1 in a time-constant manner */
293 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100294
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200295 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
296 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100297
298 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200299 X->s = X->s * ( 1 - swap ) + Y->s * swap;
300 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100301
302
303 for( i = 0; i < X->n; i++ )
304 {
305 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200306 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
307 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100308 }
309
310cleanup:
311 return( ret );
312}
313
314/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000315 * Set value from integer
316 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200317int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000318{
Janos Follath24eed8d2019-11-22 13:21:35 +0000319 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +0000320 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000321
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200322 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000323 memset( X->p, 0, X->n * ciL );
324
325 X->p[0] = ( z < 0 ) ? -z : z;
326 X->s = ( z < 0 ) ? -1 : 1;
327
328cleanup:
329
330 return( ret );
331}
332
333/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000334 * Get a specific bit
335 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000337{
Hanno Becker73d7d792018-12-11 10:35:51 +0000338 MPI_VALIDATE_RET( X != NULL );
339
Paul Bakker2f5947e2011-05-18 15:47:11 +0000340 if( X->n * biL <= pos )
341 return( 0 );
342
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200343 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000344}
345
Gilles Peskine11cdb052018-11-20 16:47:47 +0100346/* Get a specific byte, without range checks. */
347#define GET_BYTE( X, i ) \
348 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
349
Paul Bakker2f5947e2011-05-18 15:47:11 +0000350/*
351 * Set a bit to a specific value of 0 or 1
352 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200353int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000354{
355 int ret = 0;
356 size_t off = pos / biL;
357 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000358 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000359
360 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200361 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200362
Paul Bakker2f5947e2011-05-18 15:47:11 +0000363 if( X->n * biL <= pos )
364 {
365 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200366 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000367
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000369 }
370
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200371 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
372 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000373
374cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200375
Paul Bakker2f5947e2011-05-18 15:47:11 +0000376 return( ret );
377}
378
379/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200380 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000381 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000383{
Paul Bakker23986e52011-04-24 08:57:21 +0000384 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000385 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000386
387 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000388 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000389 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
390 return( count );
391
392 return( 0 );
393}
394
395/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000396 * Count leading zero bits in a given integer
397 */
398static size_t mbedtls_clz( const mbedtls_mpi_uint x )
399{
400 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100401 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000402
403 for( j = 0; j < biL; j++ )
404 {
405 if( x & mask ) break;
406
407 mask >>= 1;
408 }
409
410 return j;
411}
412
413/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200414 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000415 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200416size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000417{
Paul Bakker23986e52011-04-24 08:57:21 +0000418 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000419
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200420 if( X->n == 0 )
421 return( 0 );
422
Paul Bakker5121ce52009-01-03 21:22:43 +0000423 for( i = X->n - 1; i > 0; i-- )
424 if( X->p[i] != 0 )
425 break;
426
Simon Butcher15b15d12015-11-26 19:35:03 +0000427 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000428
Paul Bakker23986e52011-04-24 08:57:21 +0000429 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000430}
431
432/*
433 * Return the total size in bytes
434 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000436{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200437 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000438}
439
440/*
441 * Convert an ASCII character to digit value
442 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200443static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000444{
445 *d = 255;
446
447 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
448 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
449 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200451 if( *d >= (mbedtls_mpi_uint) radix )
452 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000453
454 return( 0 );
455}
456
457/*
458 * Import from an ASCII string
459 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200460int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000461{
Janos Follath24eed8d2019-11-22 13:21:35 +0000462 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000463 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200464 mbedtls_mpi_uint d;
465 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000466 MPI_VALIDATE_RET( X != NULL );
467 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000468
469 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000470 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000473
Paul Bakkerff60ee62010-03-16 21:09:09 +0000474 slen = strlen( s );
475
Paul Bakker5121ce52009-01-03 21:22:43 +0000476 if( radix == 16 )
477 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100478 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200479 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
480
Paul Bakkerff60ee62010-03-16 21:09:09 +0000481 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200483 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
484 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000485
Paul Bakker23986e52011-04-24 08:57:21 +0000486 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000487 {
Paul Bakker23986e52011-04-24 08:57:21 +0000488 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000489 {
490 X->s = -1;
491 break;
492 }
493
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200494 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200495 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000496 }
497 }
498 else
499 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200500 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000501
Paul Bakkerff60ee62010-03-16 21:09:09 +0000502 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000503 {
504 if( i == 0 && s[i] == '-' )
505 {
506 X->s = -1;
507 continue;
508 }
509
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
511 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000512
513 if( X->s == 1 )
514 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000516 }
517 else
518 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000520 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000521 }
522 }
523
524cleanup:
525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200526 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000527
528 return( ret );
529}
530
531/*
Ron Eldora16fa292018-11-20 14:07:01 +0200532 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000533 */
Ron Eldora16fa292018-11-20 14:07:01 +0200534static int mpi_write_hlp( mbedtls_mpi *X, int radix,
535 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000536{
Janos Follath24eed8d2019-11-22 13:21:35 +0000537 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200539 size_t length = 0;
540 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000541
Ron Eldora16fa292018-11-20 14:07:01 +0200542 do
543 {
544 if( length >= buflen )
545 {
546 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
547 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000548
Ron Eldora16fa292018-11-20 14:07:01 +0200549 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
550 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
551 /*
552 * Write the residue in the current position, as an ASCII character.
553 */
554 if( r < 0xA )
555 *(--p_end) = (char)( '0' + r );
556 else
557 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000558
Ron Eldora16fa292018-11-20 14:07:01 +0200559 length++;
560 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000561
Ron Eldora16fa292018-11-20 14:07:01 +0200562 memmove( *p, p_end, length );
563 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000564
565cleanup:
566
567 return( ret );
568}
569
570/*
571 * Export into an ASCII string
572 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100573int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
574 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000575{
Paul Bakker23986e52011-04-24 08:57:21 +0000576 int ret = 0;
577 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000578 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200579 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000580 MPI_VALIDATE_RET( X != NULL );
581 MPI_VALIDATE_RET( olen != NULL );
582 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000583
584 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000585 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000586
Hanno Becker23cfea02019-02-04 09:45:07 +0000587 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
588 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
589 * `n`. If radix > 4, this might be a strict
590 * overapproximation of the number of
591 * radix-adic digits needed to present `n`. */
592 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
593 * present `n`. */
594
Janos Follath80470622019-03-06 13:43:02 +0000595 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000596 n += 1; /* Compensate for the divisions above, which round down `n`
597 * in case it's not even. */
598 n += 1; /* Potential '-'-sign. */
599 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
600 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000601
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100602 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000603 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100604 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200605 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000606 }
607
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100608 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200609 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000610
611 if( X->s == -1 )
Hanno Beckerc983c812019-02-01 16:41:30 +0000612 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000613 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000614 buflen--;
615 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000616
617 if( radix == 16 )
618 {
Paul Bakker23986e52011-04-24 08:57:21 +0000619 int c;
620 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000621
Paul Bakker23986e52011-04-24 08:57:21 +0000622 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 {
Paul Bakker23986e52011-04-24 08:57:21 +0000624 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000625 {
Paul Bakker23986e52011-04-24 08:57:21 +0000626 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000627
Paul Bakker6c343d72014-07-10 14:36:19 +0200628 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000629 continue;
630
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000631 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000632 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000633 k = 1;
634 }
635 }
636 }
637 else
638 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200639 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000640
641 if( T.s == -1 )
642 T.s = 1;
643
Ron Eldora16fa292018-11-20 14:07:01 +0200644 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000645 }
646
647 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100648 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000649
650cleanup:
651
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200652 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000653
654 return( ret );
655}
656
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200657#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000658/*
659 * Read X from an opened file
660 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000662{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200663 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000664 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000665 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000666 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000667 * Buffer should have space for (short) label and decimal formatted MPI,
668 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000669 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000671
Hanno Becker73d7d792018-12-11 10:35:51 +0000672 MPI_VALIDATE_RET( X != NULL );
673 MPI_VALIDATE_RET( fin != NULL );
674
675 if( radix < 2 || radix > 16 )
676 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
677
Paul Bakker5121ce52009-01-03 21:22:43 +0000678 memset( s, 0, sizeof( s ) );
679 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000681
682 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000683 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000685
Hanno Beckerb2034b72017-04-26 11:46:46 +0100686 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
687 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000688
689 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100690 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000691 if( mpi_get_digit( &d, radix, *p ) != 0 )
692 break;
693
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200694 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000695}
696
697/*
698 * Write X into an opened file (or stdout if fout == NULL)
699 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200700int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000701{
Janos Follath24eed8d2019-11-22 13:21:35 +0000702 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000703 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000704 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000705 * Buffer should have space for (short) label and decimal formatted MPI,
706 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000707 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200708 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000709 MPI_VALIDATE_RET( X != NULL );
710
711 if( radix < 2 || radix > 16 )
712 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000713
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100714 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000715
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100716 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000717
718 if( p == NULL ) p = "";
719
720 plen = strlen( p );
721 slen = strlen( s );
722 s[slen++] = '\r';
723 s[slen++] = '\n';
724
725 if( fout != NULL )
726 {
727 if( fwrite( p, 1, plen, fout ) != plen ||
728 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200729 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000730 }
731 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200732 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000733
734cleanup:
735
736 return( ret );
737}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200738#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000739
Hanno Beckerda1655a2017-10-18 14:21:44 +0100740
741/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
742 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000743
744static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
745{
746 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100747 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000748 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100749
750 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
751 {
752 tmp <<= CHAR_BIT;
753 tmp |= (mbedtls_mpi_uint) *x_ptr;
754 }
755
Hanno Beckerf8720072018-11-08 11:53:49 +0000756 return( tmp );
757}
758
759static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
760{
761#if defined(__BYTE_ORDER__)
762
763/* Nothing to do on bigendian systems. */
764#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
765 return( x );
766#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
767
768#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
769
770/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000771#if defined(__GNUC__) && defined(__GNUC_PREREQ)
772#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000773#define have_bswap
774#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000775#endif
776
777#if defined(__clang__) && defined(__has_builtin)
778#if __has_builtin(__builtin_bswap32) && \
779 __has_builtin(__builtin_bswap64)
780#define have_bswap
781#endif
782#endif
783
Hanno Beckerf8720072018-11-08 11:53:49 +0000784#if defined(have_bswap)
785 /* The compiler is hopefully able to statically evaluate this! */
786 switch( sizeof(mbedtls_mpi_uint) )
787 {
788 case 4:
789 return( __builtin_bswap32(x) );
790 case 8:
791 return( __builtin_bswap64(x) );
792 }
793#endif
794#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
795#endif /* __BYTE_ORDER__ */
796
797 /* Fall back to C-based reordering if we don't know the byte order
798 * or we couldn't use a compiler-specific builtin. */
799 return( mpi_uint_bigendian_to_host_c( x ) );
800}
801
Hanno Becker2be8a552018-10-25 12:40:09 +0100802static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100803{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100804 mbedtls_mpi_uint *cur_limb_left;
805 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100806 if( limbs == 0 )
807 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100808
809 /*
810 * Traverse limbs and
811 * - adapt byte-order in each limb
812 * - swap the limbs themselves.
813 * For that, simultaneously traverse the limbs from left to right
814 * and from right to left, as long as the left index is not bigger
815 * than the right index (it's not a problem if limbs is odd and the
816 * indices coincide in the last iteration).
817 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100818 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
819 cur_limb_left <= cur_limb_right;
820 cur_limb_left++, cur_limb_right-- )
821 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000822 mbedtls_mpi_uint tmp;
823 /* Note that if cur_limb_left == cur_limb_right,
824 * this code effectively swaps the bytes only once. */
825 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
826 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
827 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100828 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100829}
830
Paul Bakker5121ce52009-01-03 21:22:43 +0000831/*
Janos Follatha778a942019-02-13 10:28:28 +0000832 * Import X from unsigned binary data, little endian
833 */
834int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
835 const unsigned char *buf, size_t buflen )
836{
Janos Follath24eed8d2019-11-22 13:21:35 +0000837 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000838 size_t i;
839 size_t const limbs = CHARS_TO_LIMBS( buflen );
840
841 /* Ensure that target MPI has exactly the necessary number of limbs */
842 if( X->n != limbs )
843 {
844 mbedtls_mpi_free( X );
845 mbedtls_mpi_init( X );
846 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
847 }
848
849 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
850
851 for( i = 0; i < buflen; i++ )
852 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
853
854cleanup:
855
Janos Follath171a7ef2019-02-15 16:17:45 +0000856 /*
857 * This function is also used to import keys. However, wiping the buffers
858 * upon failure is not necessary because failure only can happen before any
859 * input is copied.
860 */
Janos Follatha778a942019-02-13 10:28:28 +0000861 return( ret );
862}
863
864/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000865 * Import X from unsigned binary data, big endian
866 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200867int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000868{
Janos Follath24eed8d2019-11-22 13:21:35 +0000869 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100870 size_t const limbs = CHARS_TO_LIMBS( buflen );
871 size_t const overhead = ( limbs * ciL ) - buflen;
872 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000873
Hanno Becker8ce11a32018-12-19 16:18:52 +0000874 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000875 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
876
Hanno Becker073c1992017-10-17 15:17:27 +0100877 /* Ensure that target MPI has exactly the necessary number of limbs */
878 if( X->n != limbs )
879 {
880 mbedtls_mpi_free( X );
881 mbedtls_mpi_init( X );
882 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
883 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200884 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000885
Hanno Becker0e810b92019-01-03 17:13:11 +0000886 /* Avoid calling `memcpy` with NULL source argument,
887 * even if buflen is 0. */
888 if( buf != NULL )
889 {
890 Xp = (unsigned char*) X->p;
891 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100892
Hanno Becker0e810b92019-01-03 17:13:11 +0000893 mpi_bigendian_to_host( X->p, limbs );
894 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000895
896cleanup:
897
Janos Follath171a7ef2019-02-15 16:17:45 +0000898 /*
899 * This function is also used to import keys. However, wiping the buffers
900 * upon failure is not necessary because failure only can happen before any
901 * input is copied.
902 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000903 return( ret );
904}
905
906/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000907 * Export X into unsigned binary data, little endian
908 */
909int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
910 unsigned char *buf, size_t buflen )
911{
912 size_t stored_bytes = X->n * ciL;
913 size_t bytes_to_copy;
914 size_t i;
915
916 if( stored_bytes < buflen )
917 {
918 bytes_to_copy = stored_bytes;
919 }
920 else
921 {
922 bytes_to_copy = buflen;
923
924 /* The output buffer is smaller than the allocated size of X.
925 * However X may fit if its leading bytes are zero. */
926 for( i = bytes_to_copy; i < stored_bytes; i++ )
927 {
928 if( GET_BYTE( X, i ) != 0 )
929 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
930 }
931 }
932
933 for( i = 0; i < bytes_to_copy; i++ )
934 buf[i] = GET_BYTE( X, i );
935
936 if( stored_bytes < buflen )
937 {
938 /* Write trailing 0 bytes */
939 memset( buf + stored_bytes, 0, buflen - stored_bytes );
940 }
941
942 return( 0 );
943}
944
945/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000946 * Export X into unsigned binary data, big endian
947 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100948int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
949 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000950{
Hanno Becker73d7d792018-12-11 10:35:51 +0000951 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100952 size_t bytes_to_copy;
953 unsigned char *p;
954 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000955
Hanno Becker73d7d792018-12-11 10:35:51 +0000956 MPI_VALIDATE_RET( X != NULL );
957 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
958
959 stored_bytes = X->n * ciL;
960
Gilles Peskine11cdb052018-11-20 16:47:47 +0100961 if( stored_bytes < buflen )
962 {
963 /* There is enough space in the output buffer. Write initial
964 * null bytes and record the position at which to start
965 * writing the significant bytes. In this case, the execution
966 * trace of this function does not depend on the value of the
967 * number. */
968 bytes_to_copy = stored_bytes;
969 p = buf + buflen - stored_bytes;
970 memset( buf, 0, buflen - stored_bytes );
971 }
972 else
973 {
974 /* The output buffer is smaller than the allocated size of X.
975 * However X may fit if its leading bytes are zero. */
976 bytes_to_copy = buflen;
977 p = buf;
978 for( i = bytes_to_copy; i < stored_bytes; i++ )
979 {
980 if( GET_BYTE( X, i ) != 0 )
981 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
982 }
983 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000984
Gilles Peskine11cdb052018-11-20 16:47:47 +0100985 for( i = 0; i < bytes_to_copy; i++ )
986 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000987
988 return( 0 );
989}
990
991/*
992 * Left-shift: X <<= count
993 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200994int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000995{
Janos Follath24eed8d2019-11-22 13:21:35 +0000996 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000997 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200998 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000999 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001000
1001 v0 = count / (biL );
1002 t1 = count & (biL - 1);
1003
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001004 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +00001005
Paul Bakkerf9688572011-05-05 10:00:45 +00001006 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001007 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001008
1009 ret = 0;
1010
1011 /*
1012 * shift by count / limb_size
1013 */
1014 if( v0 > 0 )
1015 {
Paul Bakker23986e52011-04-24 08:57:21 +00001016 for( i = X->n; i > v0; i-- )
1017 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001018
Paul Bakker23986e52011-04-24 08:57:21 +00001019 for( ; i > 0; i-- )
1020 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001021 }
1022
1023 /*
1024 * shift by count % limb_size
1025 */
1026 if( t1 > 0 )
1027 {
1028 for( i = v0; i < X->n; i++ )
1029 {
1030 r1 = X->p[i] >> (biL - t1);
1031 X->p[i] <<= t1;
1032 X->p[i] |= r0;
1033 r0 = r1;
1034 }
1035 }
1036
1037cleanup:
1038
1039 return( ret );
1040}
1041
1042/*
1043 * Right-shift: X >>= count
1044 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001045int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001046{
Paul Bakker23986e52011-04-24 08:57:21 +00001047 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001048 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001049 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001050
1051 v0 = count / biL;
1052 v1 = count & (biL - 1);
1053
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001054 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001055 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001056
Paul Bakker5121ce52009-01-03 21:22:43 +00001057 /*
1058 * shift by count / limb_size
1059 */
1060 if( v0 > 0 )
1061 {
1062 for( i = 0; i < X->n - v0; i++ )
1063 X->p[i] = X->p[i + v0];
1064
1065 for( ; i < X->n; i++ )
1066 X->p[i] = 0;
1067 }
1068
1069 /*
1070 * shift by count % limb_size
1071 */
1072 if( v1 > 0 )
1073 {
Paul Bakker23986e52011-04-24 08:57:21 +00001074 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001075 {
Paul Bakker23986e52011-04-24 08:57:21 +00001076 r1 = X->p[i - 1] << (biL - v1);
1077 X->p[i - 1] >>= v1;
1078 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001079 r0 = r1;
1080 }
1081 }
1082
1083 return( 0 );
1084}
1085
1086/*
1087 * Compare unsigned values
1088 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001089int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001090{
Paul Bakker23986e52011-04-24 08:57:21 +00001091 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001092 MPI_VALIDATE_RET( X != NULL );
1093 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001094
Paul Bakker23986e52011-04-24 08:57:21 +00001095 for( i = X->n; i > 0; i-- )
1096 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001097 break;
1098
Paul Bakker23986e52011-04-24 08:57:21 +00001099 for( j = Y->n; j > 0; j-- )
1100 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001101 break;
1102
Paul Bakker23986e52011-04-24 08:57:21 +00001103 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001104 return( 0 );
1105
1106 if( i > j ) return( 1 );
1107 if( j > i ) return( -1 );
1108
Paul Bakker23986e52011-04-24 08:57:21 +00001109 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001110 {
Paul Bakker23986e52011-04-24 08:57:21 +00001111 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1112 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001113 }
1114
1115 return( 0 );
1116}
1117
1118/*
1119 * Compare signed values
1120 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001121int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001122{
Paul Bakker23986e52011-04-24 08:57:21 +00001123 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001124 MPI_VALIDATE_RET( X != NULL );
1125 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001126
Paul Bakker23986e52011-04-24 08:57:21 +00001127 for( i = X->n; i > 0; i-- )
1128 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001129 break;
1130
Paul Bakker23986e52011-04-24 08:57:21 +00001131 for( j = Y->n; j > 0; j-- )
1132 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001133 break;
1134
Paul Bakker23986e52011-04-24 08:57:21 +00001135 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001136 return( 0 );
1137
1138 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001139 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001140
1141 if( X->s > 0 && Y->s < 0 ) return( 1 );
1142 if( Y->s > 0 && X->s < 0 ) return( -1 );
1143
Paul Bakker23986e52011-04-24 08:57:21 +00001144 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001145 {
Paul Bakker23986e52011-04-24 08:57:21 +00001146 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1147 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001148 }
1149
1150 return( 0 );
1151}
1152
1153/*
1154 * Compare signed values
1155 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001156int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001157{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001158 mbedtls_mpi Y;
1159 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001160 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001161
1162 *p = ( z < 0 ) ? -z : z;
1163 Y.s = ( z < 0 ) ? -1 : 1;
1164 Y.n = 1;
1165 Y.p = p;
1166
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001167 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001168}
1169
1170/*
1171 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1172 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001173int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001174{
Janos Follath24eed8d2019-11-22 13:21:35 +00001175 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001176 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001177 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001178 MPI_VALIDATE_RET( X != NULL );
1179 MPI_VALIDATE_RET( A != NULL );
1180 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001181
1182 if( X == B )
1183 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001184 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001185 }
1186
1187 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001188 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001189
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001190 /*
1191 * X should always be positive as a result of unsigned additions.
1192 */
1193 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001194
Paul Bakker23986e52011-04-24 08:57:21 +00001195 for( j = B->n; j > 0; j-- )
1196 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001197 break;
1198
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001199 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001200
1201 o = B->p; p = X->p; c = 0;
1202
Janos Follath6c922682015-10-30 17:43:11 +01001203 /*
1204 * tmp is used because it might happen that p == o
1205 */
Paul Bakker23986e52011-04-24 08:57:21 +00001206 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001207 {
Janos Follath6c922682015-10-30 17:43:11 +01001208 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001209 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001210 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001211 }
1212
1213 while( c != 0 )
1214 {
1215 if( i >= X->n )
1216 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001217 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001218 p = X->p + i;
1219 }
1220
Paul Bakker2d319fd2012-09-16 21:34:26 +00001221 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001222 }
1223
1224cleanup:
1225
1226 return( ret );
1227}
1228
1229/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001230 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001231 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001232static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001233{
Paul Bakker23986e52011-04-24 08:57:21 +00001234 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001235 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001236
1237 for( i = c = 0; i < n; i++, s++, d++ )
1238 {
1239 z = ( *d < c ); *d -= c;
1240 c = ( *d < *s ) + z; *d -= *s;
1241 }
1242
1243 while( c != 0 )
1244 {
1245 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001246 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001247 }
1248}
1249
1250/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001251 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001252 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001253int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001254{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001255 mbedtls_mpi TB;
Janos Follath24eed8d2019-11-22 13:21:35 +00001256 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001257 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001258 MPI_VALIDATE_RET( X != NULL );
1259 MPI_VALIDATE_RET( A != NULL );
1260 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001261
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001262 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1263 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001264
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001265 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001266
1267 if( X == B )
1268 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001269 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001270 B = &TB;
1271 }
1272
1273 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001274 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001275
Paul Bakker1ef7a532009-06-20 10:50:55 +00001276 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001277 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001278 */
1279 X->s = 1;
1280
Paul Bakker5121ce52009-01-03 21:22:43 +00001281 ret = 0;
1282
Paul Bakker23986e52011-04-24 08:57:21 +00001283 for( n = B->n; n > 0; n-- )
1284 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001285 break;
1286
Paul Bakker23986e52011-04-24 08:57:21 +00001287 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001288
1289cleanup:
1290
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001291 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001292
1293 return( ret );
1294}
1295
1296/*
1297 * Signed addition: X = A + B
1298 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001299int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001300{
Hanno Becker73d7d792018-12-11 10:35:51 +00001301 int ret, s;
1302 MPI_VALIDATE_RET( X != NULL );
1303 MPI_VALIDATE_RET( A != NULL );
1304 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001305
Hanno Becker73d7d792018-12-11 10:35:51 +00001306 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001307 if( A->s * B->s < 0 )
1308 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001309 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001310 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001311 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001312 X->s = s;
1313 }
1314 else
1315 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001316 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001317 X->s = -s;
1318 }
1319 }
1320 else
1321 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001322 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001323 X->s = s;
1324 }
1325
1326cleanup:
1327
1328 return( ret );
1329}
1330
1331/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001332 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001333 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001334int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001335{
Hanno Becker73d7d792018-12-11 10:35:51 +00001336 int ret, s;
1337 MPI_VALIDATE_RET( X != NULL );
1338 MPI_VALIDATE_RET( A != NULL );
1339 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001340
Hanno Becker73d7d792018-12-11 10:35:51 +00001341 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001342 if( A->s * B->s > 0 )
1343 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001344 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001345 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001346 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001347 X->s = s;
1348 }
1349 else
1350 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001351 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001352 X->s = -s;
1353 }
1354 }
1355 else
1356 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001357 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001358 X->s = s;
1359 }
1360
1361cleanup:
1362
1363 return( ret );
1364}
1365
1366/*
1367 * Signed addition: X = A + b
1368 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001369int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001370{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001371 mbedtls_mpi _B;
1372 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001373 MPI_VALIDATE_RET( X != NULL );
1374 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001375
1376 p[0] = ( b < 0 ) ? -b : b;
1377 _B.s = ( b < 0 ) ? -1 : 1;
1378 _B.n = 1;
1379 _B.p = p;
1380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001381 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001382}
1383
1384/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001385 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001386 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001387int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001388{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001389 mbedtls_mpi _B;
1390 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001391 MPI_VALIDATE_RET( X != NULL );
1392 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001393
1394 p[0] = ( b < 0 ) ? -b : b;
1395 _B.s = ( b < 0 ) ? -1 : 1;
1396 _B.n = 1;
1397 _B.p = p;
1398
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001400}
1401
1402/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001404 */
1405static
1406#if defined(__APPLE__) && defined(__arm__)
1407/*
1408 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1409 * appears to need this to prevent bad ARM code generation at -O3.
1410 */
1411__attribute__ ((noinline))
1412#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001413void 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 +00001414{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001415 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001416
1417#if defined(MULADDC_HUIT)
1418 for( ; i >= 8; i -= 8 )
1419 {
1420 MULADDC_INIT
1421 MULADDC_HUIT
1422 MULADDC_STOP
1423 }
1424
1425 for( ; i > 0; i-- )
1426 {
1427 MULADDC_INIT
1428 MULADDC_CORE
1429 MULADDC_STOP
1430 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001431#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001432 for( ; i >= 16; i -= 16 )
1433 {
1434 MULADDC_INIT
1435 MULADDC_CORE MULADDC_CORE
1436 MULADDC_CORE MULADDC_CORE
1437 MULADDC_CORE MULADDC_CORE
1438 MULADDC_CORE MULADDC_CORE
1439
1440 MULADDC_CORE MULADDC_CORE
1441 MULADDC_CORE MULADDC_CORE
1442 MULADDC_CORE MULADDC_CORE
1443 MULADDC_CORE MULADDC_CORE
1444 MULADDC_STOP
1445 }
1446
1447 for( ; i >= 8; i -= 8 )
1448 {
1449 MULADDC_INIT
1450 MULADDC_CORE MULADDC_CORE
1451 MULADDC_CORE MULADDC_CORE
1452
1453 MULADDC_CORE MULADDC_CORE
1454 MULADDC_CORE MULADDC_CORE
1455 MULADDC_STOP
1456 }
1457
1458 for( ; i > 0; i-- )
1459 {
1460 MULADDC_INIT
1461 MULADDC_CORE
1462 MULADDC_STOP
1463 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001464#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001465
1466 t++;
1467
1468 do {
1469 *d += c; c = ( *d < c ); d++;
1470 }
1471 while( c != 0 );
1472}
1473
1474/*
1475 * Baseline multiplication: X = A * B (HAC 14.12)
1476 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001477int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001478{
Janos Follath24eed8d2019-11-22 13:21:35 +00001479 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001480 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001481 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001482 MPI_VALIDATE_RET( X != NULL );
1483 MPI_VALIDATE_RET( A != NULL );
1484 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001485
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001486 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001487
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001488 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1489 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001490
Paul Bakker23986e52011-04-24 08:57:21 +00001491 for( i = A->n; i > 0; i-- )
1492 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001493 break;
1494
Paul Bakker23986e52011-04-24 08:57:21 +00001495 for( j = B->n; j > 0; j-- )
1496 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001497 break;
1498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001499 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1500 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001501
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001502 for( ; j > 0; j-- )
1503 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001504
1505 X->s = A->s * B->s;
1506
1507cleanup:
1508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001509 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001510
1511 return( ret );
1512}
1513
1514/*
1515 * Baseline multiplication: X = A * b
1516 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001517int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001518{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001519 mbedtls_mpi _B;
1520 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001521 MPI_VALIDATE_RET( X != NULL );
1522 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001523
1524 _B.s = 1;
1525 _B.n = 1;
1526 _B.p = p;
1527 p[0] = b;
1528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001529 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001530}
1531
1532/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001533 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1534 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001535 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001536static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1537 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001538{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001539#if defined(MBEDTLS_HAVE_UDBL)
1540 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001541#else
Simon Butcher9803d072016-01-03 00:24:34 +00001542 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1543 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001544 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1545 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001546 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001547#endif
1548
Simon Butcher15b15d12015-11-26 19:35:03 +00001549 /*
1550 * Check for overflow
1551 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001552 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001553 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001554 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001555
Simon Butcherf5ba0452015-12-27 23:01:55 +00001556 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001557 }
1558
1559#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001560 dividend = (mbedtls_t_udbl) u1 << biL;
1561 dividend |= (mbedtls_t_udbl) u0;
1562 quotient = dividend / d;
1563 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1564 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1565
1566 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001567 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001568
1569 return (mbedtls_mpi_uint) quotient;
1570#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001571
1572 /*
1573 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1574 * Vol. 2 - Seminumerical Algorithms, Knuth
1575 */
1576
1577 /*
1578 * Normalize the divisor, d, and dividend, u0, u1
1579 */
1580 s = mbedtls_clz( d );
1581 d = d << s;
1582
1583 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001584 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001585 u0 = u0 << s;
1586
1587 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001588 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001589
1590 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001591 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001592
1593 /*
1594 * Find the first quotient and remainder
1595 */
1596 q1 = u1 / d1;
1597 r0 = u1 - d1 * q1;
1598
1599 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1600 {
1601 q1 -= 1;
1602 r0 += d1;
1603
1604 if ( r0 >= radix ) break;
1605 }
1606
Simon Butcherf5ba0452015-12-27 23:01:55 +00001607 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001608 q0 = rAX / d1;
1609 r0 = rAX - q0 * d1;
1610
1611 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1612 {
1613 q0 -= 1;
1614 r0 += d1;
1615
1616 if ( r0 >= radix ) break;
1617 }
1618
1619 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001620 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001621
1622 quotient = q1 * radix + q0;
1623
1624 return quotient;
1625#endif
1626}
1627
1628/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001629 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001630 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001631int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1632 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001633{
Janos Follath24eed8d2019-11-22 13:21:35 +00001634 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001635 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001637 mbedtls_mpi_uint TP2[3];
Hanno Becker73d7d792018-12-11 10:35:51 +00001638 MPI_VALIDATE_RET( A != NULL );
1639 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001640
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001641 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1642 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001643
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001644 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001645 mbedtls_mpi_init( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001646 /*
1647 * Avoid dynamic memory allocations for constant-size T2.
1648 *
1649 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1650 * so nobody increase the size of the MPI and we're safe to use an on-stack
1651 * buffer.
1652 */
Alexander K35d6d462019-10-31 14:46:45 +03001653 T2.s = 1;
Alexander Kd19a1932019-11-01 18:20:42 +03001654 T2.n = sizeof( TP2 ) / sizeof( *TP2 );
1655 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001656
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001657 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001658 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001659 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1660 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001661 return( 0 );
1662 }
1663
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001664 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1665 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001666 X.s = Y.s = 1;
1667
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001668 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1669 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1670 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001671
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001672 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001673 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001674 {
1675 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001676 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1677 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001678 }
1679 else k = 0;
1680
1681 n = X.n - 1;
1682 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001683 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001684
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001685 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001686 {
1687 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001689 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001690 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001691
1692 for( i = n; i > t ; i-- )
1693 {
1694 if( X.p[i] >= Y.p[t] )
1695 Z.p[i - t - 1] = ~0;
1696 else
1697 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001698 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1699 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001700 }
1701
Alexander K35d6d462019-10-31 14:46:45 +03001702 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1703 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1704 T2.p[2] = X.p[i];
1705
Paul Bakker5121ce52009-01-03 21:22:43 +00001706 Z.p[i - t - 1]++;
1707 do
1708 {
1709 Z.p[i - t - 1]--;
1710
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001711 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001712 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001713 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001714 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001715 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001716 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001717
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001718 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1719 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1720 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001721
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001722 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001723 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001724 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1725 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1726 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001727 Z.p[i - t - 1]--;
1728 }
1729 }
1730
1731 if( Q != NULL )
1732 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001733 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001734 Q->s = A->s * B->s;
1735 }
1736
1737 if( R != NULL )
1738 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001739 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001740 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001741 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001742
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001743 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001744 R->s = 1;
1745 }
1746
1747cleanup:
1748
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001749 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001750 mbedtls_mpi_free( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001751 mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001752
1753 return( ret );
1754}
1755
1756/*
1757 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001758 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001759int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1760 const mbedtls_mpi *A,
1761 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001762{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001763 mbedtls_mpi _B;
1764 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001765 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001766
1767 p[0] = ( b < 0 ) ? -b : b;
1768 _B.s = ( b < 0 ) ? -1 : 1;
1769 _B.n = 1;
1770 _B.p = p;
1771
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001772 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001773}
1774
1775/*
1776 * Modulo: R = A mod B
1777 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001778int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001779{
Janos Follath24eed8d2019-11-22 13:21:35 +00001780 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +00001781 MPI_VALIDATE_RET( R != NULL );
1782 MPI_VALIDATE_RET( A != NULL );
1783 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001784
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001785 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1786 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001787
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001788 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001789
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001790 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1791 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001792
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001793 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1794 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001795
1796cleanup:
1797
1798 return( ret );
1799}
1800
1801/*
1802 * Modulo: r = A mod b
1803 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001804int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001805{
Paul Bakker23986e52011-04-24 08:57:21 +00001806 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001807 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001808 MPI_VALIDATE_RET( r != NULL );
1809 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001810
1811 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001812 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001813
1814 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001815 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001816
1817 /*
1818 * handle trivial cases
1819 */
1820 if( b == 1 )
1821 {
1822 *r = 0;
1823 return( 0 );
1824 }
1825
1826 if( b == 2 )
1827 {
1828 *r = A->p[0] & 1;
1829 return( 0 );
1830 }
1831
1832 /*
1833 * general case
1834 */
Paul Bakker23986e52011-04-24 08:57:21 +00001835 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001836 {
Paul Bakker23986e52011-04-24 08:57:21 +00001837 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001838 y = ( y << biH ) | ( x >> biH );
1839 z = y / b;
1840 y -= z * b;
1841
1842 x <<= biH;
1843 y = ( y << biH ) | ( x >> biH );
1844 z = y / b;
1845 y -= z * b;
1846 }
1847
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001848 /*
1849 * If A is negative, then the current y represents a negative value.
1850 * Flipping it to the positive side.
1851 */
1852 if( A->s < 0 && y != 0 )
1853 y = b - y;
1854
Paul Bakker5121ce52009-01-03 21:22:43 +00001855 *r = y;
1856
1857 return( 0 );
1858}
1859
1860/*
1861 * Fast Montgomery initialization (thanks to Tom St Denis)
1862 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001863static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001864{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001865 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001866 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001867
1868 x = m0;
1869 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001870
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001871 for( i = biL; i >= 8; i /= 2 )
1872 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001873
1874 *mm = ~x + 1;
1875}
1876
1877/*
1878 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1879 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001880static 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 +02001881 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001882{
Paul Bakker23986e52011-04-24 08:57:21 +00001883 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001884 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001885
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001886 if( T->n < N->n + 1 || T->p == NULL )
1887 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1888
Paul Bakker5121ce52009-01-03 21:22:43 +00001889 memset( T->p, 0, T->n * ciL );
1890
1891 d = T->p;
1892 n = N->n;
1893 m = ( B->n < n ) ? B->n : n;
1894
1895 for( i = 0; i < n; i++ )
1896 {
1897 /*
1898 * T = (T + u0*B + u1*N) / 2^biL
1899 */
1900 u0 = A->p[i];
1901 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1902
1903 mpi_mul_hlp( m, B->p, d, u0 );
1904 mpi_mul_hlp( n, N->p, d, u1 );
1905
1906 *d++ = u0; d[n + 1] = 0;
1907 }
1908
Paul Bakker66d5d072014-06-17 16:39:18 +02001909 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001910
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001911 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001912 mpi_sub_hlp( n, N->p, A->p );
1913 else
1914 /* prevent timing attacks */
1915 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001916
1917 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001918}
1919
1920/*
1921 * Montgomery reduction: A = A * R^-1 mod N
1922 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001923static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1924 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001925{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001926 mbedtls_mpi_uint z = 1;
1927 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001928
Paul Bakker8ddb6452013-02-27 14:56:33 +01001929 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001930 U.p = &z;
1931
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001932 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001933}
1934
1935/*
1936 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1937 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001938int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1939 const mbedtls_mpi *E, const mbedtls_mpi *N,
1940 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001941{
Janos Follath24eed8d2019-11-22 13:21:35 +00001942 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001943 size_t wbits, wsize, one = 1;
1944 size_t i, j, nblimbs;
1945 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001946 mbedtls_mpi_uint ei, mm, state;
1947 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001948 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001949
Hanno Becker73d7d792018-12-11 10:35:51 +00001950 MPI_VALIDATE_RET( X != NULL );
1951 MPI_VALIDATE_RET( A != NULL );
1952 MPI_VALIDATE_RET( E != NULL );
1953 MPI_VALIDATE_RET( N != NULL );
1954
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001955 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001956 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001957
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001958 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1959 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001960
1961 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001962 * Init temps and window size
1963 */
1964 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001965 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1966 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001967 memset( W, 0, sizeof( W ) );
1968
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001969 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001970
1971 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1972 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1973
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001974#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001975 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1976 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001977#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001978
Paul Bakker5121ce52009-01-03 21:22:43 +00001979 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001980 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1981 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1982 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001983
1984 /*
Paul Bakker50546922012-05-19 08:40:49 +00001985 * Compensate for negative A (and correct at the end)
1986 */
1987 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001988 if( neg )
1989 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001990 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001991 Apos.s = 1;
1992 A = &Apos;
1993 }
1994
1995 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001996 * If 1st call, pre-compute R^2 mod N
1997 */
1998 if( _RR == NULL || _RR->p == NULL )
1999 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002000 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2001 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2002 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002003
2004 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002005 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002006 }
2007 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002008 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002009
2010 /*
2011 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2012 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002013 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2014 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002015 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002017
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002018 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002019
2020 /*
2021 * X = R^2 * R^-1 mod N = R mod N
2022 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002024 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002025
2026 if( wsize > 1 )
2027 {
2028 /*
2029 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2030 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002031 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002032
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002033 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2034 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002035
2036 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002037 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002038
Paul Bakker5121ce52009-01-03 21:22:43 +00002039 /*
2040 * W[i] = W[i - 1] * W[1]
2041 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002042 for( i = j + 1; i < ( one << wsize ); i++ )
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[i], N->n + 1 ) );
2045 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002046
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002047 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002048 }
2049 }
2050
2051 nblimbs = E->n;
2052 bufsize = 0;
2053 nbits = 0;
2054 wbits = 0;
2055 state = 0;
2056
2057 while( 1 )
2058 {
2059 if( bufsize == 0 )
2060 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002061 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002062 break;
2063
Paul Bakker0d7702c2013-10-29 16:18:35 +01002064 nblimbs--;
2065
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002066 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002067 }
2068
2069 bufsize--;
2070
2071 ei = (E->p[nblimbs] >> bufsize) & 1;
2072
2073 /*
2074 * skip leading 0s
2075 */
2076 if( ei == 0 && state == 0 )
2077 continue;
2078
2079 if( ei == 0 && state == 1 )
2080 {
2081 /*
2082 * out of window, square X
2083 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002084 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002085 continue;
2086 }
2087
2088 /*
2089 * add ei to current window
2090 */
2091 state = 2;
2092
2093 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002094 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002095
2096 if( nbits == wsize )
2097 {
2098 /*
2099 * X = X^wsize R^-1 mod N
2100 */
2101 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002102 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002103
2104 /*
2105 * X = X * W[wbits] R^-1 mod N
2106 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002107 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002108
2109 state--;
2110 nbits = 0;
2111 wbits = 0;
2112 }
2113 }
2114
2115 /*
2116 * process the remaining bits
2117 */
2118 for( i = 0; i < nbits; i++ )
2119 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002120 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002121
2122 wbits <<= 1;
2123
Paul Bakker66d5d072014-06-17 16:39:18 +02002124 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002125 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002126 }
2127
2128 /*
2129 * X = A^E * R * R^-1 mod N = A^E mod N
2130 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002131 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002132
Hanno Beckera4af1c42017-04-18 09:07:45 +01002133 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002134 {
2135 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002136 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002137 }
2138
Paul Bakker5121ce52009-01-03 21:22:43 +00002139cleanup:
2140
Paul Bakker66d5d072014-06-17 16:39:18 +02002141 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002142 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002143
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002144 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002145
Paul Bakker75a28602014-03-31 12:08:17 +02002146 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002147 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002148
2149 return( ret );
2150}
2151
Paul Bakker5121ce52009-01-03 21:22:43 +00002152/*
2153 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2154 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002155int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002156{
Janos Follath24eed8d2019-11-22 13:21:35 +00002157 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002158 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002159 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002160
Hanno Becker73d7d792018-12-11 10:35:51 +00002161 MPI_VALIDATE_RET( G != NULL );
2162 MPI_VALIDATE_RET( A != NULL );
2163 MPI_VALIDATE_RET( B != NULL );
2164
Alexander Ke8ad49f2019-08-16 16:16:07 +03002165 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002166
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002167 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2168 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002170 lz = mbedtls_mpi_lsb( &TA );
2171 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002172
Paul Bakker66d5d072014-06-17 16:39:18 +02002173 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002174 lz = lzt;
2175
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002176 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2177 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002178
Paul Bakker5121ce52009-01-03 21:22:43 +00002179 TA.s = TB.s = 1;
2180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002181 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002182 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002183 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2184 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002185
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002186 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002187 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2189 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002190 }
2191 else
2192 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002193 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2194 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002195 }
2196 }
2197
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2199 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002200
2201cleanup:
2202
Alexander Ke8ad49f2019-08-16 16:16:07 +03002203 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002204
2205 return( ret );
2206}
2207
Paul Bakker33dc46b2014-04-30 16:11:39 +02002208/*
2209 * Fill X with size bytes of random.
2210 *
2211 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002212 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002213 * deterministic, eg for tests).
2214 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002215int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002216 int (*f_rng)(void *, unsigned char *, size_t),
2217 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002218{
Janos Follath24eed8d2019-11-22 13:21:35 +00002219 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker6dab6202019-01-02 16:42:29 +00002220 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002221 size_t const overhead = ( limbs * ciL ) - size;
2222 unsigned char *Xp;
2223
Hanno Becker8ce11a32018-12-19 16:18:52 +00002224 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002225 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002226
Hanno Beckerda1655a2017-10-18 14:21:44 +01002227 /* Ensure that target MPI has exactly the necessary number of limbs */
2228 if( X->n != limbs )
2229 {
2230 mbedtls_mpi_free( X );
2231 mbedtls_mpi_init( X );
2232 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2233 }
2234 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002235
Hanno Beckerda1655a2017-10-18 14:21:44 +01002236 Xp = (unsigned char*) X->p;
2237 f_rng( p_rng, Xp + overhead, size );
2238
Hanno Becker2be8a552018-10-25 12:40:09 +01002239 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002240
2241cleanup:
2242 return( ret );
2243}
2244
Paul Bakker5121ce52009-01-03 21:22:43 +00002245/*
2246 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2247 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002248int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002249{
Janos Follath24eed8d2019-11-22 13:21:35 +00002250 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002251 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002252 MPI_VALIDATE_RET( X != NULL );
2253 MPI_VALIDATE_RET( A != NULL );
2254 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002255
Hanno Becker4bcb4912017-04-18 15:49:39 +01002256 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002257 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002259 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2260 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2261 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002262
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002263 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002264
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002265 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002266 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002267 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002268 goto cleanup;
2269 }
2270
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002271 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2272 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2273 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2274 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002275
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002276 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2277 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2278 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2279 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002280
2281 do
2282 {
2283 while( ( TU.p[0] & 1 ) == 0 )
2284 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002285 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002286
2287 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2288 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002289 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2290 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002291 }
2292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002293 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2294 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002295 }
2296
2297 while( ( TV.p[0] & 1 ) == 0 )
2298 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002300
2301 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2302 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002303 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2304 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002305 }
2306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2308 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002309 }
2310
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002311 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002312 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002313 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2314 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2315 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002316 }
2317 else
2318 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002319 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2320 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2321 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002322 }
2323 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002324 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002326 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2327 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002329 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2330 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002332 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002333
2334cleanup:
2335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002336 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2337 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2338 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002339
2340 return( ret );
2341}
2342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002343#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002344
Paul Bakker5121ce52009-01-03 21:22:43 +00002345static const int small_prime[] =
2346{
2347 3, 5, 7, 11, 13, 17, 19, 23,
2348 29, 31, 37, 41, 43, 47, 53, 59,
2349 61, 67, 71, 73, 79, 83, 89, 97,
2350 101, 103, 107, 109, 113, 127, 131, 137,
2351 139, 149, 151, 157, 163, 167, 173, 179,
2352 181, 191, 193, 197, 199, 211, 223, 227,
2353 229, 233, 239, 241, 251, 257, 263, 269,
2354 271, 277, 281, 283, 293, 307, 311, 313,
2355 317, 331, 337, 347, 349, 353, 359, 367,
2356 373, 379, 383, 389, 397, 401, 409, 419,
2357 421, 431, 433, 439, 443, 449, 457, 461,
2358 463, 467, 479, 487, 491, 499, 503, 509,
2359 521, 523, 541, 547, 557, 563, 569, 571,
2360 577, 587, 593, 599, 601, 607, 613, 617,
2361 619, 631, 641, 643, 647, 653, 659, 661,
2362 673, 677, 683, 691, 701, 709, 719, 727,
2363 733, 739, 743, 751, 757, 761, 769, 773,
2364 787, 797, 809, 811, 821, 823, 827, 829,
2365 839, 853, 857, 859, 863, 877, 881, 883,
2366 887, 907, 911, 919, 929, 937, 941, 947,
2367 953, 967, 971, 977, 983, 991, 997, -103
2368};
2369
2370/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002371 * Small divisors test (X must be positive)
2372 *
2373 * Return values:
2374 * 0: no small factor (possible prime, more tests needed)
2375 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002377 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002378 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002379static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002380{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002381 int ret = 0;
2382 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002384
Paul Bakker5121ce52009-01-03 21:22:43 +00002385 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002386 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002387
2388 for( i = 0; small_prime[i] > 0; i++ )
2389 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002390 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002391 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002393 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002394
2395 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002397 }
2398
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002399cleanup:
2400 return( ret );
2401}
2402
2403/*
2404 * Miller-Rabin pseudo-primality test (HAC 4.24)
2405 */
Janos Follathda31fa12018-09-03 14:45:23 +01002406static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002407 int (*f_rng)(void *, unsigned char *, size_t),
2408 void *p_rng )
2409{
Pascal Junodb99183d2015-03-11 16:49:45 +01002410 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002411 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002412 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002413
Hanno Becker8ce11a32018-12-19 16:18:52 +00002414 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002415 MPI_VALIDATE_RET( f_rng != NULL );
2416
2417 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2418 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002419 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002420
Paul Bakker5121ce52009-01-03 21:22:43 +00002421 /*
2422 * W = |X| - 1
2423 * R = W >> lsb( W )
2424 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002425 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2426 s = mbedtls_mpi_lsb( &W );
2427 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2428 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002429
Janos Follathda31fa12018-09-03 14:45:23 +01002430 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002431 {
2432 /*
2433 * pick a random A, 1 < A < |X| - 1
2434 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002435 count = 0;
2436 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002437 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002438
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002439 j = mbedtls_mpi_bitlen( &A );
2440 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002441 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002442 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002443 }
2444
2445 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002446 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2447 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002448 }
2449
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002450 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2451 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002452
2453 /*
2454 * A = A^R mod |X|
2455 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002456 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002457
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002458 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2459 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002460 continue;
2461
2462 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002463 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002464 {
2465 /*
2466 * A = A * A mod |X|
2467 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002468 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2469 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002471 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002472 break;
2473
2474 j++;
2475 }
2476
2477 /*
2478 * not prime if A != |X| - 1 or A == 1
2479 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002480 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2481 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002482 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002483 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002484 break;
2485 }
2486 }
2487
2488cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002489 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2490 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002491 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002492
2493 return( ret );
2494}
2495
2496/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002497 * Pseudo-primality test: small factors, then Miller-Rabin
2498 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002499int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2500 int (*f_rng)(void *, unsigned char *, size_t),
2501 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002502{
Janos Follath24eed8d2019-11-22 13:21:35 +00002503 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002504 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002505 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002506 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002507
2508 XX.s = 1;
2509 XX.n = X->n;
2510 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002511
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002512 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2513 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2514 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002515
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002516 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002517 return( 0 );
2518
2519 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2520 {
2521 if( ret == 1 )
2522 return( 0 );
2523
2524 return( ret );
2525 }
2526
Janos Follathda31fa12018-09-03 14:45:23 +01002527 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002528}
2529
Janos Follatha0b67c22018-09-18 14:48:23 +01002530#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002531/*
2532 * Pseudo-primality test, error probability 2^-80
2533 */
2534int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2535 int (*f_rng)(void *, unsigned char *, size_t),
2536 void *p_rng )
2537{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002538 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002539 MPI_VALIDATE_RET( f_rng != NULL );
2540
Janos Follatha0b67c22018-09-18 14:48:23 +01002541 /*
2542 * In the past our key generation aimed for an error rate of at most
2543 * 2^-80. Since this function is deprecated, aim for the same certainty
2544 * here as well.
2545 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002546 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002547}
Janos Follatha0b67c22018-09-18 14:48:23 +01002548#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002549
2550/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002551 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002552 *
Janos Follathf301d232018-08-14 13:34:01 +01002553 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2554 * be either 1024 bits or 1536 bits long, and flags must contain
2555 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002556 */
Janos Follath7c025a92018-08-14 11:08:41 +01002557int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002558 int (*f_rng)(void *, unsigned char *, size_t),
2559 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002560{
Jethro Beekman66689272018-02-14 19:24:10 -08002561#ifdef MBEDTLS_HAVE_INT64
2562// ceil(2^63.5)
2563#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2564#else
2565// ceil(2^31.5)
2566#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2567#endif
2568 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002569 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002570 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002571 mbedtls_mpi_uint r;
2572 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002573
Hanno Becker8ce11a32018-12-19 16:18:52 +00002574 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002575 MPI_VALIDATE_RET( f_rng != NULL );
2576
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002577 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2578 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002579
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002580 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002581
2582 n = BITS_TO_LIMBS( nbits );
2583
Janos Follathda31fa12018-09-03 14:45:23 +01002584 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2585 {
2586 /*
2587 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2588 */
2589 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2590 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2591 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2592 }
2593 else
2594 {
2595 /*
2596 * 2^-100 error probability, number of rounds computed based on HAC,
2597 * fact 4.48
2598 */
2599 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2600 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2601 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2602 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2603 }
2604
Jethro Beekman66689272018-02-14 19:24:10 -08002605 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002606 {
Jethro Beekman66689272018-02-14 19:24:10 -08002607 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2608 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2609 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2610
2611 k = n * biL;
2612 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2613 X->p[0] |= 1;
2614
Janos Follath7c025a92018-08-14 11:08:41 +01002615 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002616 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002617 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002619 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002620 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002621 }
Jethro Beekman66689272018-02-14 19:24:10 -08002622 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002623 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002624 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002625 * An necessary condition for Y and X = 2Y + 1 to be prime
2626 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2627 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002628 */
Jethro Beekman66689272018-02-14 19:24:10 -08002629
2630 X->p[0] |= 2;
2631
2632 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2633 if( r == 0 )
2634 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2635 else if( r == 1 )
2636 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2637
2638 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2639 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2640 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2641
2642 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002643 {
Jethro Beekman66689272018-02-14 19:24:10 -08002644 /*
2645 * First, check small factors for X and Y
2646 * before doing Miller-Rabin on any of them
2647 */
2648 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2649 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002650 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002651 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002652 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002653 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002654 goto cleanup;
2655
2656 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2657 goto cleanup;
2658
2659 /*
2660 * Next candidates. We want to preserve Y = (X-1) / 2 and
2661 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2662 * so up Y by 6 and X by 12.
2663 */
2664 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2665 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002666 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002667 }
2668 }
2669
2670cleanup:
2671
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002672 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002673
2674 return( ret );
2675}
2676
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002677#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002678
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002679#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002680
Paul Bakker23986e52011-04-24 08:57:21 +00002681#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002682
2683static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2684{
2685 { 693, 609, 21 },
2686 { 1764, 868, 28 },
2687 { 768454923, 542167814, 1 }
2688};
2689
Paul Bakker5121ce52009-01-03 21:22:43 +00002690/*
2691 * Checkup routine
2692 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002693int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002694{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002695 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002696 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002697
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002698 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2699 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002700
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002701 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002702 "EFE021C2645FD1DC586E69184AF4A31E" \
2703 "D5F53E93B5F123FA41680867BA110131" \
2704 "944FE7952E2517337780CB0DB80E61AA" \
2705 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2706
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002707 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002708 "B2E7EFD37075B9F03FF989C7C5051C20" \
2709 "34D2A323810251127E7BF8625A4F49A5" \
2710 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2711 "5B5C25763222FEFCCFC38B832366C29E" ) );
2712
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002713 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002714 "0066A198186C18C10B2F5ED9B522752A" \
2715 "9830B69916E535C8F047518A889A43A5" \
2716 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2717
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002718 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002719
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002720 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002721 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2722 "9E857EA95A03512E2BAE7391688D264A" \
2723 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2724 "8001B72E848A38CAE1C65F78E56ABDEF" \
2725 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2726 "ECF677152EF804370C1A305CAF3B5BF1" \
2727 "30879B56C61DE584A0F53A2447A51E" ) );
2728
2729 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002730 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002731
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002732 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002733 {
2734 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002735 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002736
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002737 ret = 1;
2738 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002739 }
2740
2741 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002742 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002743
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002744 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002745
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002746 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002747 "256567336059E52CAE22925474705F39A94" ) );
2748
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002749 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002750 "6613F26162223DF488E9CD48CC132C7A" \
2751 "0AC93C701B001B092E4E5B9F73BCD27B" \
2752 "9EE50D0657C77F374E903CDFA4C642" ) );
2753
2754 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002755 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002756
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002757 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2758 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002759 {
2760 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002761 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002762
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002763 ret = 1;
2764 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002765 }
2766
2767 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002768 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002769
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002770 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002771
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002772 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002773 "36E139AEA55215609D2816998ED020BB" \
2774 "BD96C37890F65171D948E9BC7CBAA4D9" \
2775 "325D24D6A3C12710F10A09FA08AB87" ) );
2776
2777 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002778 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002779
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002780 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002781 {
2782 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002783 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002784
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002785 ret = 1;
2786 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002787 }
2788
2789 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002790 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002791
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002792 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002793
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002794 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002795 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2796 "C3DBA76456363A10869622EAC2DD84EC" \
2797 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2798
2799 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002800 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002801
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002802 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002803 {
2804 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002805 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002806
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002807 ret = 1;
2808 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002809 }
2810
2811 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002812 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002813
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002814 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002815 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002816
Paul Bakker66d5d072014-06-17 16:39:18 +02002817 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002818 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002819 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2820 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002821
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002822 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002823
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002824 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002825 {
2826 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002827 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002828
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002829 ret = 1;
2830 goto cleanup;
2831 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002832 }
2833
2834 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002835 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002836
Paul Bakker5121ce52009-01-03 21:22:43 +00002837cleanup:
2838
2839 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002840 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002841
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002842 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2843 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002844
2845 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002846 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002847
2848 return( ret );
2849}
2850
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002851#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002852
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002853#endif /* MBEDTLS_BIGNUM_C */