blob: 33534874fc0d6ead02745b86c15cd90a48bae677 [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/*
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200247 * Conditionally assign dest = src, without leaking information
248 * about whether the assignment was made or not.
249 * dest and src must be arrays of limbs of size n.
250 * assign must be 0 or 1.
251 */
252static void mpi_safe_cond_assign( size_t n,
253 mbedtls_mpi_uint *dest,
254 const mbedtls_mpi_uint *src,
255 unsigned char assign )
256{
257 size_t i;
258 for( i = 0; i < n; i++ )
259 dest[i] = dest[i] * ( 1 - assign ) + src[i] * assign;
260}
261
262/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100263 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100264 * about whether the assignment was made or not.
265 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100266 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100268{
269 int ret = 0;
270 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000271 MPI_VALIDATE_RET( X != NULL );
272 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100273
Pascal Junodb99183d2015-03-11 16:49:45 +0100274 /* make sure assign is 0 or 1 in a time-constant manner */
275 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100276
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200277 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100278
Paul Bakker66d5d072014-06-17 16:39:18 +0200279 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100280
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200281 mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100282
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200283 for( i = Y->n; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200284 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100285
286cleanup:
287 return( ret );
288}
289
290/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100291 * Conditionally swap X and Y, without leaking information
292 * about whether the swap was made or not.
293 * Here it is not ok to simply swap the pointers, which whould lead to
294 * different memory access patterns when X and Y are used afterwards.
295 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200296int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100297{
298 int ret, s;
299 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200300 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000301 MPI_VALIDATE_RET( X != NULL );
302 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100303
304 if( X == Y )
305 return( 0 );
306
Pascal Junodb99183d2015-03-11 16:49:45 +0100307 /* make sure swap is 0 or 1 in a time-constant manner */
308 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100309
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200310 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
311 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100312
313 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200314 X->s = X->s * ( 1 - swap ) + Y->s * swap;
315 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100316
317
318 for( i = 0; i < X->n; i++ )
319 {
320 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200321 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
322 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100323 }
324
325cleanup:
326 return( ret );
327}
328
329/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000330 * Set value from integer
331 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200332int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000333{
Janos Follath24eed8d2019-11-22 13:21:35 +0000334 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +0000335 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000336
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200337 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000338 memset( X->p, 0, X->n * ciL );
339
340 X->p[0] = ( z < 0 ) ? -z : z;
341 X->s = ( z < 0 ) ? -1 : 1;
342
343cleanup:
344
345 return( ret );
346}
347
348/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000349 * Get a specific bit
350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000352{
Hanno Becker73d7d792018-12-11 10:35:51 +0000353 MPI_VALIDATE_RET( X != NULL );
354
Paul Bakker2f5947e2011-05-18 15:47:11 +0000355 if( X->n * biL <= pos )
356 return( 0 );
357
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200358 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000359}
360
Gilles Peskine11cdb052018-11-20 16:47:47 +0100361/* Get a specific byte, without range checks. */
362#define GET_BYTE( X, i ) \
363 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
364
Paul Bakker2f5947e2011-05-18 15:47:11 +0000365/*
366 * Set a bit to a specific value of 0 or 1
367 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000369{
370 int ret = 0;
371 size_t off = pos / biL;
372 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000373 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000374
375 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200376 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200377
Paul Bakker2f5947e2011-05-18 15:47:11 +0000378 if( X->n * biL <= pos )
379 {
380 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200381 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000384 }
385
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200386 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
387 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000388
389cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200390
Paul Bakker2f5947e2011-05-18 15:47:11 +0000391 return( ret );
392}
393
394/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200395 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000396 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000398{
Paul Bakker23986e52011-04-24 08:57:21 +0000399 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000400 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000401
402 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000403 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000404 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
405 return( count );
406
407 return( 0 );
408}
409
410/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000411 * Count leading zero bits in a given integer
412 */
413static size_t mbedtls_clz( const mbedtls_mpi_uint x )
414{
415 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100416 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000417
418 for( j = 0; j < biL; j++ )
419 {
420 if( x & mask ) break;
421
422 mask >>= 1;
423 }
424
425 return j;
426}
427
428/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200429 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000430 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200431size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000432{
Paul Bakker23986e52011-04-24 08:57:21 +0000433 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000434
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200435 if( X->n == 0 )
436 return( 0 );
437
Paul Bakker5121ce52009-01-03 21:22:43 +0000438 for( i = X->n - 1; i > 0; i-- )
439 if( X->p[i] != 0 )
440 break;
441
Simon Butcher15b15d12015-11-26 19:35:03 +0000442 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000443
Paul Bakker23986e52011-04-24 08:57:21 +0000444 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000445}
446
447/*
448 * Return the total size in bytes
449 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200450size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000451{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200452 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000453}
454
455/*
456 * Convert an ASCII character to digit value
457 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000459{
460 *d = 255;
461
462 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
463 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
464 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200466 if( *d >= (mbedtls_mpi_uint) radix )
467 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000468
469 return( 0 );
470}
471
472/*
473 * Import from an ASCII string
474 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200475int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000476{
Janos Follath24eed8d2019-11-22 13:21:35 +0000477 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000478 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479 mbedtls_mpi_uint d;
480 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000481 MPI_VALIDATE_RET( X != NULL );
482 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
484 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000485 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000486
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000488
Paul Bakkerff60ee62010-03-16 21:09:09 +0000489 slen = strlen( s );
490
Paul Bakker5121ce52009-01-03 21:22:43 +0000491 if( radix == 16 )
492 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100493 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200494 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
495
Paul Bakkerff60ee62010-03-16 21:09:09 +0000496 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000497
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
499 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000500
Paul Bakker23986e52011-04-24 08:57:21 +0000501 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000502 {
Paul Bakker23986e52011-04-24 08:57:21 +0000503 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000504 {
505 X->s = -1;
506 break;
507 }
508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200510 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000511 }
512 }
513 else
514 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000516
Paul Bakkerff60ee62010-03-16 21:09:09 +0000517 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000518 {
519 if( i == 0 && s[i] == '-' )
520 {
521 X->s = -1;
522 continue;
523 }
524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
526 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000527
528 if( X->s == 1 )
529 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000531 }
532 else
533 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000535 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000536 }
537 }
538
539cleanup:
540
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200541 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000542
543 return( ret );
544}
545
546/*
Ron Eldora16fa292018-11-20 14:07:01 +0200547 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000548 */
Ron Eldora16fa292018-11-20 14:07:01 +0200549static int mpi_write_hlp( mbedtls_mpi *X, int radix,
550 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000551{
Janos Follath24eed8d2019-11-22 13:21:35 +0000552 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200554 size_t length = 0;
555 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000556
Ron Eldora16fa292018-11-20 14:07:01 +0200557 do
558 {
559 if( length >= buflen )
560 {
561 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
562 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000563
Ron Eldora16fa292018-11-20 14:07:01 +0200564 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
565 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
566 /*
567 * Write the residue in the current position, as an ASCII character.
568 */
569 if( r < 0xA )
570 *(--p_end) = (char)( '0' + r );
571 else
572 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000573
Ron Eldora16fa292018-11-20 14:07:01 +0200574 length++;
575 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000576
Ron Eldora16fa292018-11-20 14:07:01 +0200577 memmove( *p, p_end, length );
578 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000579
580cleanup:
581
582 return( ret );
583}
584
585/*
586 * Export into an ASCII string
587 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100588int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
589 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000590{
Paul Bakker23986e52011-04-24 08:57:21 +0000591 int ret = 0;
592 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000593 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000595 MPI_VALIDATE_RET( X != NULL );
596 MPI_VALIDATE_RET( olen != NULL );
597 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000598
599 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000600 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000601
Hanno Becker23cfea02019-02-04 09:45:07 +0000602 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
603 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
604 * `n`. If radix > 4, this might be a strict
605 * overapproximation of the number of
606 * radix-adic digits needed to present `n`. */
607 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
608 * present `n`. */
609
Janos Follath80470622019-03-06 13:43:02 +0000610 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000611 n += 1; /* Compensate for the divisions above, which round down `n`
612 * in case it's not even. */
613 n += 1; /* Potential '-'-sign. */
614 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
615 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000616
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100617 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000618 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100619 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000621 }
622
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100623 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200624 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000625
626 if( X->s == -1 )
Hanno Beckerc983c812019-02-01 16:41:30 +0000627 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000628 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000629 buflen--;
630 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000631
632 if( radix == 16 )
633 {
Paul Bakker23986e52011-04-24 08:57:21 +0000634 int c;
635 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000636
Paul Bakker23986e52011-04-24 08:57:21 +0000637 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000638 {
Paul Bakker23986e52011-04-24 08:57:21 +0000639 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000640 {
Paul Bakker23986e52011-04-24 08:57:21 +0000641 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000642
Paul Bakker6c343d72014-07-10 14:36:19 +0200643 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000644 continue;
645
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000646 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000647 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000648 k = 1;
649 }
650 }
651 }
652 else
653 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200654 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000655
656 if( T.s == -1 )
657 T.s = 1;
658
Ron Eldora16fa292018-11-20 14:07:01 +0200659 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000660 }
661
662 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100663 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000664
665cleanup:
666
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000668
669 return( ret );
670}
671
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000673/*
674 * Read X from an opened file
675 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000677{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000679 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000680 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000681 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000682 * Buffer should have space for (short) label and decimal formatted MPI,
683 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000684 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000686
Hanno Becker73d7d792018-12-11 10:35:51 +0000687 MPI_VALIDATE_RET( X != NULL );
688 MPI_VALIDATE_RET( fin != NULL );
689
690 if( radix < 2 || radix > 16 )
691 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
692
Paul Bakker5121ce52009-01-03 21:22:43 +0000693 memset( s, 0, sizeof( s ) );
694 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000696
697 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000698 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200699 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000700
Hanno Beckerb2034b72017-04-26 11:46:46 +0100701 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
702 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000703
704 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100705 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000706 if( mpi_get_digit( &d, radix, *p ) != 0 )
707 break;
708
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200709 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000710}
711
712/*
713 * Write X into an opened file (or stdout if fout == NULL)
714 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200715int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000716{
Janos Follath24eed8d2019-11-22 13:21:35 +0000717 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000718 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000719 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000720 * Buffer should have space for (short) label and decimal formatted MPI,
721 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000722 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200723 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000724 MPI_VALIDATE_RET( X != NULL );
725
726 if( radix < 2 || radix > 16 )
727 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000728
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100729 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000730
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100731 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000732
733 if( p == NULL ) p = "";
734
735 plen = strlen( p );
736 slen = strlen( s );
737 s[slen++] = '\r';
738 s[slen++] = '\n';
739
740 if( fout != NULL )
741 {
742 if( fwrite( p, 1, plen, fout ) != plen ||
743 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200744 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000745 }
746 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200747 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000748
749cleanup:
750
751 return( ret );
752}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200753#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000754
Hanno Beckerda1655a2017-10-18 14:21:44 +0100755
756/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
757 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000758
759static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
760{
761 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100762 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000763 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100764
765 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
766 {
767 tmp <<= CHAR_BIT;
768 tmp |= (mbedtls_mpi_uint) *x_ptr;
769 }
770
Hanno Beckerf8720072018-11-08 11:53:49 +0000771 return( tmp );
772}
773
774static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
775{
776#if defined(__BYTE_ORDER__)
777
778/* Nothing to do on bigendian systems. */
779#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
780 return( x );
781#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
782
783#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
784
785/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000786#if defined(__GNUC__) && defined(__GNUC_PREREQ)
787#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000788#define have_bswap
789#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000790#endif
791
792#if defined(__clang__) && defined(__has_builtin)
793#if __has_builtin(__builtin_bswap32) && \
794 __has_builtin(__builtin_bswap64)
795#define have_bswap
796#endif
797#endif
798
Hanno Beckerf8720072018-11-08 11:53:49 +0000799#if defined(have_bswap)
800 /* The compiler is hopefully able to statically evaluate this! */
801 switch( sizeof(mbedtls_mpi_uint) )
802 {
803 case 4:
804 return( __builtin_bswap32(x) );
805 case 8:
806 return( __builtin_bswap64(x) );
807 }
808#endif
809#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
810#endif /* __BYTE_ORDER__ */
811
812 /* Fall back to C-based reordering if we don't know the byte order
813 * or we couldn't use a compiler-specific builtin. */
814 return( mpi_uint_bigendian_to_host_c( x ) );
815}
816
Hanno Becker2be8a552018-10-25 12:40:09 +0100817static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100818{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100819 mbedtls_mpi_uint *cur_limb_left;
820 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100821 if( limbs == 0 )
822 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100823
824 /*
825 * Traverse limbs and
826 * - adapt byte-order in each limb
827 * - swap the limbs themselves.
828 * For that, simultaneously traverse the limbs from left to right
829 * and from right to left, as long as the left index is not bigger
830 * than the right index (it's not a problem if limbs is odd and the
831 * indices coincide in the last iteration).
832 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100833 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
834 cur_limb_left <= cur_limb_right;
835 cur_limb_left++, cur_limb_right-- )
836 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000837 mbedtls_mpi_uint tmp;
838 /* Note that if cur_limb_left == cur_limb_right,
839 * this code effectively swaps the bytes only once. */
840 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
841 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
842 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100843 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100844}
845
Paul Bakker5121ce52009-01-03 21:22:43 +0000846/*
Janos Follatha778a942019-02-13 10:28:28 +0000847 * Import X from unsigned binary data, little endian
848 */
849int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
850 const unsigned char *buf, size_t buflen )
851{
Janos Follath24eed8d2019-11-22 13:21:35 +0000852 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000853 size_t i;
854 size_t const limbs = CHARS_TO_LIMBS( buflen );
855
856 /* Ensure that target MPI has exactly the necessary number of limbs */
857 if( X->n != limbs )
858 {
859 mbedtls_mpi_free( X );
860 mbedtls_mpi_init( X );
861 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
862 }
863
864 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
865
866 for( i = 0; i < buflen; i++ )
867 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
868
869cleanup:
870
Janos Follath171a7ef2019-02-15 16:17:45 +0000871 /*
872 * This function is also used to import keys. However, wiping the buffers
873 * upon failure is not necessary because failure only can happen before any
874 * input is copied.
875 */
Janos Follatha778a942019-02-13 10:28:28 +0000876 return( ret );
877}
878
879/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000880 * Import X from unsigned binary data, big endian
881 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200882int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000883{
Janos Follath24eed8d2019-11-22 13:21:35 +0000884 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100885 size_t const limbs = CHARS_TO_LIMBS( buflen );
886 size_t const overhead = ( limbs * ciL ) - buflen;
887 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000888
Hanno Becker8ce11a32018-12-19 16:18:52 +0000889 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000890 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
891
Hanno Becker073c1992017-10-17 15:17:27 +0100892 /* Ensure that target MPI has exactly the necessary number of limbs */
893 if( X->n != limbs )
894 {
895 mbedtls_mpi_free( X );
896 mbedtls_mpi_init( X );
897 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
898 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200899 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000900
Hanno Becker0e810b92019-01-03 17:13:11 +0000901 /* Avoid calling `memcpy` with NULL source argument,
902 * even if buflen is 0. */
903 if( buf != NULL )
904 {
905 Xp = (unsigned char*) X->p;
906 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100907
Hanno Becker0e810b92019-01-03 17:13:11 +0000908 mpi_bigendian_to_host( X->p, limbs );
909 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000910
911cleanup:
912
Janos Follath171a7ef2019-02-15 16:17:45 +0000913 /*
914 * This function is also used to import keys. However, wiping the buffers
915 * upon failure is not necessary because failure only can happen before any
916 * input is copied.
917 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000918 return( ret );
919}
920
921/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000922 * Export X into unsigned binary data, little endian
923 */
924int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
925 unsigned char *buf, size_t buflen )
926{
927 size_t stored_bytes = X->n * ciL;
928 size_t bytes_to_copy;
929 size_t i;
930
931 if( stored_bytes < buflen )
932 {
933 bytes_to_copy = stored_bytes;
934 }
935 else
936 {
937 bytes_to_copy = buflen;
938
939 /* The output buffer is smaller than the allocated size of X.
940 * However X may fit if its leading bytes are zero. */
941 for( i = bytes_to_copy; i < stored_bytes; i++ )
942 {
943 if( GET_BYTE( X, i ) != 0 )
944 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
945 }
946 }
947
948 for( i = 0; i < bytes_to_copy; i++ )
949 buf[i] = GET_BYTE( X, i );
950
951 if( stored_bytes < buflen )
952 {
953 /* Write trailing 0 bytes */
954 memset( buf + stored_bytes, 0, buflen - stored_bytes );
955 }
956
957 return( 0 );
958}
959
960/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000961 * Export X into unsigned binary data, big endian
962 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100963int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
964 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000965{
Hanno Becker73d7d792018-12-11 10:35:51 +0000966 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100967 size_t bytes_to_copy;
968 unsigned char *p;
969 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000970
Hanno Becker73d7d792018-12-11 10:35:51 +0000971 MPI_VALIDATE_RET( X != NULL );
972 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
973
974 stored_bytes = X->n * ciL;
975
Gilles Peskine11cdb052018-11-20 16:47:47 +0100976 if( stored_bytes < buflen )
977 {
978 /* There is enough space in the output buffer. Write initial
979 * null bytes and record the position at which to start
980 * writing the significant bytes. In this case, the execution
981 * trace of this function does not depend on the value of the
982 * number. */
983 bytes_to_copy = stored_bytes;
984 p = buf + buflen - stored_bytes;
985 memset( buf, 0, buflen - stored_bytes );
986 }
987 else
988 {
989 /* The output buffer is smaller than the allocated size of X.
990 * However X may fit if its leading bytes are zero. */
991 bytes_to_copy = buflen;
992 p = buf;
993 for( i = bytes_to_copy; i < stored_bytes; i++ )
994 {
995 if( GET_BYTE( X, i ) != 0 )
996 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
997 }
998 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000999
Gilles Peskine11cdb052018-11-20 16:47:47 +01001000 for( i = 0; i < bytes_to_copy; i++ )
1001 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +00001002
1003 return( 0 );
1004}
1005
1006/*
1007 * Left-shift: X <<= count
1008 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001009int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001010{
Janos Follath24eed8d2019-11-22 13:21:35 +00001011 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001012 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001013 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001014 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001015
1016 v0 = count / (biL );
1017 t1 = count & (biL - 1);
1018
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001019 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +00001020
Paul Bakkerf9688572011-05-05 10:00:45 +00001021 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001022 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001023
1024 ret = 0;
1025
1026 /*
1027 * shift by count / limb_size
1028 */
1029 if( v0 > 0 )
1030 {
Paul Bakker23986e52011-04-24 08:57:21 +00001031 for( i = X->n; i > v0; i-- )
1032 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001033
Paul Bakker23986e52011-04-24 08:57:21 +00001034 for( ; i > 0; i-- )
1035 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001036 }
1037
1038 /*
1039 * shift by count % limb_size
1040 */
1041 if( t1 > 0 )
1042 {
1043 for( i = v0; i < X->n; i++ )
1044 {
1045 r1 = X->p[i] >> (biL - t1);
1046 X->p[i] <<= t1;
1047 X->p[i] |= r0;
1048 r0 = r1;
1049 }
1050 }
1051
1052cleanup:
1053
1054 return( ret );
1055}
1056
1057/*
1058 * Right-shift: X >>= count
1059 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001060int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001061{
Paul Bakker23986e52011-04-24 08:57:21 +00001062 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001063 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001064 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001065
1066 v0 = count / biL;
1067 v1 = count & (biL - 1);
1068
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001069 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001070 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001071
Paul Bakker5121ce52009-01-03 21:22:43 +00001072 /*
1073 * shift by count / limb_size
1074 */
1075 if( v0 > 0 )
1076 {
1077 for( i = 0; i < X->n - v0; i++ )
1078 X->p[i] = X->p[i + v0];
1079
1080 for( ; i < X->n; i++ )
1081 X->p[i] = 0;
1082 }
1083
1084 /*
1085 * shift by count % limb_size
1086 */
1087 if( v1 > 0 )
1088 {
Paul Bakker23986e52011-04-24 08:57:21 +00001089 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001090 {
Paul Bakker23986e52011-04-24 08:57:21 +00001091 r1 = X->p[i - 1] << (biL - v1);
1092 X->p[i - 1] >>= v1;
1093 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001094 r0 = r1;
1095 }
1096 }
1097
1098 return( 0 );
1099}
1100
1101/*
1102 * Compare unsigned values
1103 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001104int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001105{
Paul Bakker23986e52011-04-24 08:57:21 +00001106 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001107 MPI_VALIDATE_RET( X != NULL );
1108 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001109
Paul Bakker23986e52011-04-24 08:57:21 +00001110 for( i = X->n; i > 0; i-- )
1111 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001112 break;
1113
Paul Bakker23986e52011-04-24 08:57:21 +00001114 for( j = Y->n; j > 0; j-- )
1115 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001116 break;
1117
Paul Bakker23986e52011-04-24 08:57:21 +00001118 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001119 return( 0 );
1120
1121 if( i > j ) return( 1 );
1122 if( j > i ) return( -1 );
1123
Paul Bakker23986e52011-04-24 08:57:21 +00001124 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001125 {
Paul Bakker23986e52011-04-24 08:57:21 +00001126 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1127 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001128 }
1129
1130 return( 0 );
1131}
1132
1133/*
1134 * Compare signed values
1135 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001136int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001137{
Paul Bakker23986e52011-04-24 08:57:21 +00001138 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001139 MPI_VALIDATE_RET( X != NULL );
1140 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001141
Paul Bakker23986e52011-04-24 08:57:21 +00001142 for( i = X->n; i > 0; i-- )
1143 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001144 break;
1145
Paul Bakker23986e52011-04-24 08:57:21 +00001146 for( j = Y->n; j > 0; j-- )
1147 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001148 break;
1149
Paul Bakker23986e52011-04-24 08:57:21 +00001150 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001151 return( 0 );
1152
1153 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001154 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001155
1156 if( X->s > 0 && Y->s < 0 ) return( 1 );
1157 if( Y->s > 0 && X->s < 0 ) return( -1 );
1158
Paul Bakker23986e52011-04-24 08:57:21 +00001159 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001160 {
Paul Bakker23986e52011-04-24 08:57:21 +00001161 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1162 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001163 }
1164
1165 return( 0 );
1166}
1167
Janos Follath3f6f0e42019-10-14 09:09:32 +01001168/** Decide if an integer is less than the other, without branches.
1169 *
1170 * \param x First integer.
1171 * \param y Second integer.
1172 *
1173 * \return 1 if \p x is less than \p y, 0 otherwise
1174 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001175static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1176 const mbedtls_mpi_uint y )
Janos Follathee6abce2019-09-05 14:47:19 +01001177{
1178 mbedtls_mpi_uint ret;
1179 mbedtls_mpi_uint cond;
1180
1181 /*
1182 * Check if the most significant bits (MSB) of the operands are different.
1183 */
1184 cond = ( x ^ y );
1185 /*
1186 * If the MSB are the same then the difference x-y will be negative (and
1187 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1188 */
1189 ret = ( x - y ) & ~cond;
1190 /*
1191 * If the MSB are different, then the operand with the MSB of 1 is the
1192 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1193 * the MSB of y is 0.)
1194 */
1195 ret |= y & cond;
1196
1197
Janos Follatha0f732b2019-10-14 08:59:14 +01001198 ret = ret >> ( biL - 1 );
Janos Follathee6abce2019-09-05 14:47:19 +01001199
Janos Follath67ce6472019-10-29 15:08:46 +00001200 return (unsigned) ret;
Janos Follathee6abce2019-09-05 14:47:19 +01001201}
1202
1203/*
1204 * Compare signed values in constant time
1205 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001206int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1207 unsigned *ret )
Janos Follathee6abce2019-09-05 14:47:19 +01001208{
1209 size_t i;
Janos Follathbb5147f2019-10-28 12:23:18 +00001210 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath5e614ce2019-10-28 12:31:34 +00001211 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathee6abce2019-09-05 14:47:19 +01001212
1213 MPI_VALIDATE_RET( X != NULL );
1214 MPI_VALIDATE_RET( Y != NULL );
1215 MPI_VALIDATE_RET( ret != NULL );
1216
1217 if( X->n != Y->n )
1218 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1219
1220 /*
Janos Follath73ba9ec2019-10-28 12:12:15 +00001221 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1222 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathee6abce2019-09-05 14:47:19 +01001223 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001224 X_is_negative = ( X->s & 2 ) >> 1;
1225 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follath0e5532d2019-10-11 14:21:53 +01001226
1227 /*
1228 * If the signs are different, then the positive operand is the bigger.
Janos Follath5e614ce2019-10-28 12:31:34 +00001229 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1230 * is false if X is positive (X_is_negative == 0).
Janos Follath0e5532d2019-10-11 14:21:53 +01001231 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001232 cond = ( X_is_negative ^ Y_is_negative );
1233 *ret = cond & X_is_negative;
Janos Follath0e5532d2019-10-11 14:21:53 +01001234
1235 /*
Janos Follathbb5147f2019-10-28 12:23:18 +00001236 * This is a constant-time function. We might have the result, but we still
Janos Follath0e5532d2019-10-11 14:21:53 +01001237 * need to go through the loop. Record if we have the result already.
1238 */
Janos Follathee6abce2019-09-05 14:47:19 +01001239 done = cond;
1240
1241 for( i = X->n; i > 0; i-- )
1242 {
1243 /*
Janos Follath30702422019-11-05 12:24:52 +00001244 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1245 * X and Y are negative.
Janos Follath0e5532d2019-10-11 14:21:53 +01001246 *
1247 * Again even if we can make a decision, we just mark the result and
1248 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001249 */
Janos Follath30702422019-11-05 12:24:52 +00001250 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1251 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathc50e6d52019-10-28 12:37:21 +00001252 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001253
1254 /*
Janos Follath30702422019-11-05 12:24:52 +00001255 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1256 * X and Y are positive.
Janos Follath0e5532d2019-10-11 14:21:53 +01001257 *
1258 * Again even if we can make a decision, we just mark the result and
1259 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001260 */
Janos Follath30702422019-11-05 12:24:52 +00001261 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1262 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathc50e6d52019-10-28 12:37:21 +00001263 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001264 }
1265
1266 return( 0 );
1267}
1268
Paul Bakker5121ce52009-01-03 21:22:43 +00001269/*
1270 * Compare signed values
1271 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001272int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001273{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001274 mbedtls_mpi Y;
1275 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001276 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001277
1278 *p = ( z < 0 ) ? -z : z;
1279 Y.s = ( z < 0 ) ? -1 : 1;
1280 Y.n = 1;
1281 Y.p = p;
1282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001283 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001284}
1285
1286/*
1287 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1288 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001289int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001290{
Janos Follath24eed8d2019-11-22 13:21:35 +00001291 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001292 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001293 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001294 MPI_VALIDATE_RET( X != NULL );
1295 MPI_VALIDATE_RET( A != NULL );
1296 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001297
1298 if( X == B )
1299 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001300 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001301 }
1302
1303 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001304 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001305
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001306 /*
1307 * X should always be positive as a result of unsigned additions.
1308 */
1309 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001310
Paul Bakker23986e52011-04-24 08:57:21 +00001311 for( j = B->n; j > 0; j-- )
1312 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001313 break;
1314
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001315 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001316
1317 o = B->p; p = X->p; c = 0;
1318
Janos Follath6c922682015-10-30 17:43:11 +01001319 /*
1320 * tmp is used because it might happen that p == o
1321 */
Paul Bakker23986e52011-04-24 08:57:21 +00001322 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001323 {
Janos Follath6c922682015-10-30 17:43:11 +01001324 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001325 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001326 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001327 }
1328
1329 while( c != 0 )
1330 {
1331 if( i >= X->n )
1332 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001333 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001334 p = X->p + i;
1335 }
1336
Paul Bakker2d319fd2012-09-16 21:34:26 +00001337 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001338 }
1339
1340cleanup:
1341
1342 return( ret );
1343}
1344
1345/*
Gilles Peskine2a82f722020-06-04 15:00:49 +02001346 * Helper for mbedtls_mpi subtraction:
1347 * d -= s where d and s have the same size and d >= s.
Paul Bakker5121ce52009-01-03 21:22:43 +00001348 */
Gilles Peskine742f1a42020-06-04 15:01:32 +02001349static void mpi_sub_hlp( size_t n,
1350 const mbedtls_mpi_uint *s,
1351 mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001352{
Paul Bakker23986e52011-04-24 08:57:21 +00001353 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001354 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001355
1356 for( i = c = 0; i < n; i++, s++, d++ )
1357 {
1358 z = ( *d < c ); *d -= c;
1359 c = ( *d < *s ) + z; *d -= *s;
1360 }
1361
1362 while( c != 0 )
1363 {
1364 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001365 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001366 }
1367}
1368
1369/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001370 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001371 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001373{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001374 mbedtls_mpi TB;
Janos Follath24eed8d2019-11-22 13:21:35 +00001375 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001376 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001377 MPI_VALIDATE_RET( X != NULL );
1378 MPI_VALIDATE_RET( A != NULL );
1379 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001381 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1382 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001383
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001384 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001385
1386 if( X == B )
1387 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001388 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001389 B = &TB;
1390 }
1391
1392 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001393 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001394
Paul Bakker1ef7a532009-06-20 10:50:55 +00001395 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001396 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001397 */
1398 X->s = 1;
1399
Paul Bakker5121ce52009-01-03 21:22:43 +00001400 ret = 0;
1401
Paul Bakker23986e52011-04-24 08:57:21 +00001402 for( n = B->n; n > 0; n-- )
1403 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001404 break;
1405
Paul Bakker23986e52011-04-24 08:57:21 +00001406 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001407
1408cleanup:
1409
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001410 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001411
1412 return( ret );
1413}
1414
1415/*
1416 * Signed addition: X = A + B
1417 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001418int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001419{
Hanno Becker73d7d792018-12-11 10:35:51 +00001420 int ret, s;
1421 MPI_VALIDATE_RET( X != NULL );
1422 MPI_VALIDATE_RET( A != NULL );
1423 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001424
Hanno Becker73d7d792018-12-11 10:35:51 +00001425 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001426 if( A->s * B->s < 0 )
1427 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001428 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001429 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001430 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001431 X->s = s;
1432 }
1433 else
1434 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001435 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001436 X->s = -s;
1437 }
1438 }
1439 else
1440 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001441 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001442 X->s = s;
1443 }
1444
1445cleanup:
1446
1447 return( ret );
1448}
1449
1450/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001451 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001452 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001453int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001454{
Hanno Becker73d7d792018-12-11 10:35:51 +00001455 int ret, s;
1456 MPI_VALIDATE_RET( X != NULL );
1457 MPI_VALIDATE_RET( A != NULL );
1458 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001459
Hanno Becker73d7d792018-12-11 10:35:51 +00001460 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001461 if( A->s * B->s > 0 )
1462 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001463 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001464 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001465 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001466 X->s = s;
1467 }
1468 else
1469 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001470 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001471 X->s = -s;
1472 }
1473 }
1474 else
1475 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001476 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001477 X->s = s;
1478 }
1479
1480cleanup:
1481
1482 return( ret );
1483}
1484
1485/*
1486 * Signed addition: X = A + b
1487 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001488int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001489{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001490 mbedtls_mpi _B;
1491 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001492 MPI_VALIDATE_RET( X != NULL );
1493 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001494
1495 p[0] = ( b < 0 ) ? -b : b;
1496 _B.s = ( b < 0 ) ? -1 : 1;
1497 _B.n = 1;
1498 _B.p = p;
1499
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001500 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001501}
1502
1503/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001504 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001505 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001507{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001508 mbedtls_mpi _B;
1509 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001510 MPI_VALIDATE_RET( X != NULL );
1511 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001512
1513 p[0] = ( b < 0 ) ? -b : b;
1514 _B.s = ( b < 0 ) ? -1 : 1;
1515 _B.n = 1;
1516 _B.p = p;
1517
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001518 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001519}
1520
1521/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001522 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001523 */
1524static
1525#if defined(__APPLE__) && defined(__arm__)
1526/*
1527 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1528 * appears to need this to prevent bad ARM code generation at -O3.
1529 */
1530__attribute__ ((noinline))
1531#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001532void 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 +00001533{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001534 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001535
1536#if defined(MULADDC_HUIT)
1537 for( ; i >= 8; i -= 8 )
1538 {
1539 MULADDC_INIT
1540 MULADDC_HUIT
1541 MULADDC_STOP
1542 }
1543
1544 for( ; i > 0; i-- )
1545 {
1546 MULADDC_INIT
1547 MULADDC_CORE
1548 MULADDC_STOP
1549 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001550#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001551 for( ; i >= 16; i -= 16 )
1552 {
1553 MULADDC_INIT
1554 MULADDC_CORE MULADDC_CORE
1555 MULADDC_CORE MULADDC_CORE
1556 MULADDC_CORE MULADDC_CORE
1557 MULADDC_CORE MULADDC_CORE
1558
1559 MULADDC_CORE MULADDC_CORE
1560 MULADDC_CORE MULADDC_CORE
1561 MULADDC_CORE MULADDC_CORE
1562 MULADDC_CORE MULADDC_CORE
1563 MULADDC_STOP
1564 }
1565
1566 for( ; i >= 8; i -= 8 )
1567 {
1568 MULADDC_INIT
1569 MULADDC_CORE MULADDC_CORE
1570 MULADDC_CORE MULADDC_CORE
1571
1572 MULADDC_CORE MULADDC_CORE
1573 MULADDC_CORE MULADDC_CORE
1574 MULADDC_STOP
1575 }
1576
1577 for( ; i > 0; i-- )
1578 {
1579 MULADDC_INIT
1580 MULADDC_CORE
1581 MULADDC_STOP
1582 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001583#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001584
1585 t++;
1586
1587 do {
1588 *d += c; c = ( *d < c ); d++;
1589 }
1590 while( c != 0 );
1591}
1592
1593/*
1594 * Baseline multiplication: X = A * B (HAC 14.12)
1595 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001596int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001597{
Janos Follath24eed8d2019-11-22 13:21:35 +00001598 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001599 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001600 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001601 MPI_VALIDATE_RET( X != NULL );
1602 MPI_VALIDATE_RET( A != NULL );
1603 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001604
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001605 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001606
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001607 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1608 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001609
Paul Bakker23986e52011-04-24 08:57:21 +00001610 for( i = A->n; i > 0; i-- )
1611 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001612 break;
1613
Paul Bakker23986e52011-04-24 08:57:21 +00001614 for( j = B->n; j > 0; j-- )
1615 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001616 break;
1617
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001618 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1619 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001620
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001621 for( ; j > 0; j-- )
1622 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001623
1624 X->s = A->s * B->s;
1625
1626cleanup:
1627
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001628 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001629
1630 return( ret );
1631}
1632
1633/*
1634 * Baseline multiplication: X = A * b
1635 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001637{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001638 mbedtls_mpi _B;
1639 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001640 MPI_VALIDATE_RET( X != NULL );
1641 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001642
1643 _B.s = 1;
1644 _B.n = 1;
1645 _B.p = p;
1646 p[0] = b;
1647
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001648 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001649}
1650
1651/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001652 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1653 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001654 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001655static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1656 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001657{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001658#if defined(MBEDTLS_HAVE_UDBL)
1659 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001660#else
Simon Butcher9803d072016-01-03 00:24:34 +00001661 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1662 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001663 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1664 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001665 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001666#endif
1667
Simon Butcher15b15d12015-11-26 19:35:03 +00001668 /*
1669 * Check for overflow
1670 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001671 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001672 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001673 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001674
Simon Butcherf5ba0452015-12-27 23:01:55 +00001675 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001676 }
1677
1678#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001679 dividend = (mbedtls_t_udbl) u1 << biL;
1680 dividend |= (mbedtls_t_udbl) u0;
1681 quotient = dividend / d;
1682 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1683 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1684
1685 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001686 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001687
1688 return (mbedtls_mpi_uint) quotient;
1689#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001690
1691 /*
1692 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1693 * Vol. 2 - Seminumerical Algorithms, Knuth
1694 */
1695
1696 /*
1697 * Normalize the divisor, d, and dividend, u0, u1
1698 */
1699 s = mbedtls_clz( d );
1700 d = d << s;
1701
1702 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001703 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001704 u0 = u0 << s;
1705
1706 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001707 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001708
1709 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001710 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001711
1712 /*
1713 * Find the first quotient and remainder
1714 */
1715 q1 = u1 / d1;
1716 r0 = u1 - d1 * q1;
1717
1718 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1719 {
1720 q1 -= 1;
1721 r0 += d1;
1722
1723 if ( r0 >= radix ) break;
1724 }
1725
Simon Butcherf5ba0452015-12-27 23:01:55 +00001726 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001727 q0 = rAX / d1;
1728 r0 = rAX - q0 * d1;
1729
1730 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1731 {
1732 q0 -= 1;
1733 r0 += d1;
1734
1735 if ( r0 >= radix ) break;
1736 }
1737
1738 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001739 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001740
1741 quotient = q1 * radix + q0;
1742
1743 return quotient;
1744#endif
1745}
1746
1747/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001748 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001749 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001750int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1751 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001752{
Janos Follath24eed8d2019-11-22 13:21:35 +00001753 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001754 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001756 mbedtls_mpi_uint TP2[3];
Hanno Becker73d7d792018-12-11 10:35:51 +00001757 MPI_VALIDATE_RET( A != NULL );
1758 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001759
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001760 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1761 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001762
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001763 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001764 mbedtls_mpi_init( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001765 /*
1766 * Avoid dynamic memory allocations for constant-size T2.
1767 *
1768 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1769 * so nobody increase the size of the MPI and we're safe to use an on-stack
1770 * buffer.
1771 */
Alexander K35d6d462019-10-31 14:46:45 +03001772 T2.s = 1;
Alexander Kd19a1932019-11-01 18:20:42 +03001773 T2.n = sizeof( TP2 ) / sizeof( *TP2 );
1774 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001775
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001776 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001777 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001778 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1779 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001780 return( 0 );
1781 }
1782
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001783 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1784 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001785 X.s = Y.s = 1;
1786
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001787 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1788 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1789 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001790
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001791 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001792 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001793 {
1794 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001795 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1796 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001797 }
1798 else k = 0;
1799
1800 n = X.n - 1;
1801 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001802 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001803
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001804 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001805 {
1806 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001807 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001808 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001809 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001810
1811 for( i = n; i > t ; i-- )
1812 {
1813 if( X.p[i] >= Y.p[t] )
1814 Z.p[i - t - 1] = ~0;
1815 else
1816 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001817 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1818 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001819 }
1820
Alexander K35d6d462019-10-31 14:46:45 +03001821 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1822 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1823 T2.p[2] = X.p[i];
1824
Paul Bakker5121ce52009-01-03 21:22:43 +00001825 Z.p[i - t - 1]++;
1826 do
1827 {
1828 Z.p[i - t - 1]--;
1829
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001831 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001832 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001833 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001834 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001835 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001836
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001837 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1838 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1839 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001840
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001841 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001842 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001843 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1844 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1845 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846 Z.p[i - t - 1]--;
1847 }
1848 }
1849
1850 if( Q != NULL )
1851 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001852 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001853 Q->s = A->s * B->s;
1854 }
1855
1856 if( R != NULL )
1857 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001858 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001859 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001860 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001861
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001862 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001863 R->s = 1;
1864 }
1865
1866cleanup:
1867
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001868 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001869 mbedtls_mpi_free( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001870 mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001871
1872 return( ret );
1873}
1874
1875/*
1876 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001877 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001878int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1879 const mbedtls_mpi *A,
1880 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001881{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882 mbedtls_mpi _B;
1883 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001884 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001885
1886 p[0] = ( b < 0 ) ? -b : b;
1887 _B.s = ( b < 0 ) ? -1 : 1;
1888 _B.n = 1;
1889 _B.p = p;
1890
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001891 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001892}
1893
1894/*
1895 * Modulo: R = A mod B
1896 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001897int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001898{
Janos Follath24eed8d2019-11-22 13:21:35 +00001899 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +00001900 MPI_VALIDATE_RET( R != NULL );
1901 MPI_VALIDATE_RET( A != NULL );
1902 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001903
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001904 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1905 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001906
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001907 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001908
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001909 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1910 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001911
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001912 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1913 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001914
1915cleanup:
1916
1917 return( ret );
1918}
1919
1920/*
1921 * Modulo: r = A mod b
1922 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001923int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001924{
Paul Bakker23986e52011-04-24 08:57:21 +00001925 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001926 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001927 MPI_VALIDATE_RET( r != NULL );
1928 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001929
1930 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001931 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001932
1933 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001934 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001935
1936 /*
1937 * handle trivial cases
1938 */
1939 if( b == 1 )
1940 {
1941 *r = 0;
1942 return( 0 );
1943 }
1944
1945 if( b == 2 )
1946 {
1947 *r = A->p[0] & 1;
1948 return( 0 );
1949 }
1950
1951 /*
1952 * general case
1953 */
Paul Bakker23986e52011-04-24 08:57:21 +00001954 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001955 {
Paul Bakker23986e52011-04-24 08:57:21 +00001956 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001957 y = ( y << biH ) | ( x >> biH );
1958 z = y / b;
1959 y -= z * b;
1960
1961 x <<= biH;
1962 y = ( y << biH ) | ( x >> biH );
1963 z = y / b;
1964 y -= z * b;
1965 }
1966
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001967 /*
1968 * If A is negative, then the current y represents a negative value.
1969 * Flipping it to the positive side.
1970 */
1971 if( A->s < 0 && y != 0 )
1972 y = b - y;
1973
Paul Bakker5121ce52009-01-03 21:22:43 +00001974 *r = y;
1975
1976 return( 0 );
1977}
1978
1979/*
1980 * Fast Montgomery initialization (thanks to Tom St Denis)
1981 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001982static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001983{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001984 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001985 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001986
1987 x = m0;
1988 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001989
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001990 for( i = biL; i >= 8; i /= 2 )
1991 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001992
1993 *mm = ~x + 1;
1994}
1995
Gilles Peskine2a82f722020-06-04 15:00:49 +02001996/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1997 *
1998 * \param[in,out] A One of the numbers to multiply.
1999 * It must have at least one more limb than N
2000 * (A->n >= N->n + 1).
2001 * On successful completion, A contains the result of
2002 * the multiplication A * B * R^-1 mod N where
2003 * R = (2^ciL)^n.
2004 * \param[in] B One of the numbers to multiply.
2005 * It must be nonzero and must not have more limbs than N
2006 * (B->n <= N->n).
2007 * \param[in] N The modulo. N must be odd.
2008 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
2009 * This is -N^-1 mod 2^ciL.
2010 * \param[in,out] T A bignum for temporary storage.
2011 * It must be at least twice the limb size of N plus 2
2012 * (T->n >= 2 * (N->n + 1)).
2013 * Its initial content is unused and
2014 * its final content is indeterminate.
2015 * Note that unlike the usual convention in the library
2016 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00002017 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002018static void 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 +02002019 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002020{
Paul Bakker23986e52011-04-24 08:57:21 +00002021 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002022 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00002023
2024 memset( T->p, 0, T->n * ciL );
2025
2026 d = T->p;
2027 n = N->n;
2028 m = ( B->n < n ) ? B->n : n;
2029
2030 for( i = 0; i < n; i++ )
2031 {
2032 /*
2033 * T = (T + u0*B + u1*N) / 2^biL
2034 */
2035 u0 = A->p[i];
2036 u1 = ( d[0] + u0 * B->p[0] ) * mm;
2037
2038 mpi_mul_hlp( m, B->p, d, u0 );
2039 mpi_mul_hlp( n, N->p, d, u1 );
2040
2041 *d++ = u0; d[n + 1] = 0;
2042 }
2043
Paul Bakker66d5d072014-06-17 16:39:18 +02002044 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002045
Gilles Peskine2a82f722020-06-04 15:00:49 +02002046 /* If A >= N then A -= N. Do the subtraction unconditionally to prevent
2047 * timing attacks. Modify T as a side effect. */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002048 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002049 mpi_sub_hlp( n, N->p, A->p );
2050 else
2051 /* prevent timing attacks */
2052 mpi_sub_hlp( n, A->p, T->p );
2053}
2054
2055/*
2056 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02002057 *
2058 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00002059 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002060static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
2061 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002062{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002063 mbedtls_mpi_uint z = 1;
2064 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00002065
Paul Bakker8ddb6452013-02-27 14:56:33 +01002066 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00002067 U.p = &z;
2068
Gilles Peskine4e91d472020-06-04 20:55:15 +02002069 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002070}
2071
2072/*
2073 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2074 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002075int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2076 const mbedtls_mpi *E, const mbedtls_mpi *N,
2077 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00002078{
Janos Follath24eed8d2019-11-22 13:21:35 +00002079 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002080 size_t wbits, wsize, one = 1;
2081 size_t i, j, nblimbs;
2082 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002083 mbedtls_mpi_uint ei, mm, state;
2084 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002085 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002086
Hanno Becker73d7d792018-12-11 10:35:51 +00002087 MPI_VALIDATE_RET( X != NULL );
2088 MPI_VALIDATE_RET( A != NULL );
2089 MPI_VALIDATE_RET( E != NULL );
2090 MPI_VALIDATE_RET( N != NULL );
2091
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01002092 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002093 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002094
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002095 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2096 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002097
2098 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002099 * Init temps and window size
2100 */
2101 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002102 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2103 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00002104 memset( W, 0, sizeof( W ) );
2105
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002106 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00002107
2108 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2109 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2110
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002111#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002112 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2113 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002114#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002115
Paul Bakker5121ce52009-01-03 21:22:43 +00002116 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002117 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2118 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2119 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002120
2121 /*
Paul Bakker50546922012-05-19 08:40:49 +00002122 * Compensate for negative A (and correct at the end)
2123 */
2124 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002125 if( neg )
2126 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002127 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002128 Apos.s = 1;
2129 A = &Apos;
2130 }
2131
2132 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002133 * If 1st call, pre-compute R^2 mod N
2134 */
2135 if( _RR == NULL || _RR->p == NULL )
2136 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002137 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2138 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2139 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002140
2141 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002142 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002143 }
2144 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002146
2147 /*
2148 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2149 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002150 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2151 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002152 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002153 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002154
Gilles Peskine4e91d472020-06-04 20:55:15 +02002155 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002156
2157 /*
2158 * X = R^2 * R^-1 mod N = R mod N
2159 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine4e91d472020-06-04 20:55:15 +02002161 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002162
2163 if( wsize > 1 )
2164 {
2165 /*
2166 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2167 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002168 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002170 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2171 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002172
2173 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002174 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002175
Paul Bakker5121ce52009-01-03 21:22:43 +00002176 /*
2177 * W[i] = W[i - 1] * W[1]
2178 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002179 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002180 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002181 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2182 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002183
Gilles Peskine4e91d472020-06-04 20:55:15 +02002184 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002185 }
2186 }
2187
2188 nblimbs = E->n;
2189 bufsize = 0;
2190 nbits = 0;
2191 wbits = 0;
2192 state = 0;
2193
2194 while( 1 )
2195 {
2196 if( bufsize == 0 )
2197 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002198 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002199 break;
2200
Paul Bakker0d7702c2013-10-29 16:18:35 +01002201 nblimbs--;
2202
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002203 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002204 }
2205
2206 bufsize--;
2207
2208 ei = (E->p[nblimbs] >> bufsize) & 1;
2209
2210 /*
2211 * skip leading 0s
2212 */
2213 if( ei == 0 && state == 0 )
2214 continue;
2215
2216 if( ei == 0 && state == 1 )
2217 {
2218 /*
2219 * out of window, square X
2220 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002221 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002222 continue;
2223 }
2224
2225 /*
2226 * add ei to current window
2227 */
2228 state = 2;
2229
2230 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002231 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002232
2233 if( nbits == wsize )
2234 {
2235 /*
2236 * X = X^wsize R^-1 mod N
2237 */
2238 for( i = 0; i < wsize; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002239 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002240
2241 /*
2242 * X = X * W[wbits] R^-1 mod N
2243 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002244 mpi_montmul( X, &W[wbits], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002245
2246 state--;
2247 nbits = 0;
2248 wbits = 0;
2249 }
2250 }
2251
2252 /*
2253 * process the remaining bits
2254 */
2255 for( i = 0; i < nbits; i++ )
2256 {
Gilles Peskine4e91d472020-06-04 20:55:15 +02002257 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002258
2259 wbits <<= 1;
2260
Paul Bakker66d5d072014-06-17 16:39:18 +02002261 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002262 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002263 }
2264
2265 /*
2266 * X = A^E * R * R^-1 mod N = A^E mod N
2267 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002268 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002269
Hanno Beckera4af1c42017-04-18 09:07:45 +01002270 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002271 {
2272 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002273 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002274 }
2275
Paul Bakker5121ce52009-01-03 21:22:43 +00002276cleanup:
2277
Paul Bakker66d5d072014-06-17 16:39:18 +02002278 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002279 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002280
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002281 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002282
Paul Bakker75a28602014-03-31 12:08:17 +02002283 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002284 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002285
2286 return( ret );
2287}
2288
Paul Bakker5121ce52009-01-03 21:22:43 +00002289/*
2290 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2291 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002292int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002293{
Janos Follath24eed8d2019-11-22 13:21:35 +00002294 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002295 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002296 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002297
Hanno Becker73d7d792018-12-11 10:35:51 +00002298 MPI_VALIDATE_RET( G != NULL );
2299 MPI_VALIDATE_RET( A != NULL );
2300 MPI_VALIDATE_RET( B != NULL );
2301
Alexander Ke8ad49f2019-08-16 16:16:07 +03002302 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002303
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002304 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2305 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 lz = mbedtls_mpi_lsb( &TA );
2308 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002309
Paul Bakker66d5d072014-06-17 16:39:18 +02002310 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002311 lz = lzt;
2312
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002313 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2314 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002315
Paul Bakker5121ce52009-01-03 21:22:43 +00002316 TA.s = TB.s = 1;
2317
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002318 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002319 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002320 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2321 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002322
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002323 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002324 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002325 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2326 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002327 }
2328 else
2329 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2331 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002332 }
2333 }
2334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2336 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002337
2338cleanup:
2339
Alexander Ke8ad49f2019-08-16 16:16:07 +03002340 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002341
2342 return( ret );
2343}
2344
Paul Bakker33dc46b2014-04-30 16:11:39 +02002345/*
2346 * Fill X with size bytes of random.
2347 *
2348 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002349 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002350 * deterministic, eg for tests).
2351 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002352int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002353 int (*f_rng)(void *, unsigned char *, size_t),
2354 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002355{
Janos Follath24eed8d2019-11-22 13:21:35 +00002356 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker6dab6202019-01-02 16:42:29 +00002357 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002358 size_t const overhead = ( limbs * ciL ) - size;
2359 unsigned char *Xp;
2360
Hanno Becker8ce11a32018-12-19 16:18:52 +00002361 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002362 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002363
Hanno Beckerda1655a2017-10-18 14:21:44 +01002364 /* Ensure that target MPI has exactly the necessary number of limbs */
2365 if( X->n != limbs )
2366 {
2367 mbedtls_mpi_free( X );
2368 mbedtls_mpi_init( X );
2369 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2370 }
2371 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002372
Hanno Beckerda1655a2017-10-18 14:21:44 +01002373 Xp = (unsigned char*) X->p;
2374 f_rng( p_rng, Xp + overhead, size );
2375
Hanno Becker2be8a552018-10-25 12:40:09 +01002376 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002377
2378cleanup:
2379 return( ret );
2380}
2381
Paul Bakker5121ce52009-01-03 21:22:43 +00002382/*
2383 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2384 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002386{
Janos Follath24eed8d2019-11-22 13:21:35 +00002387 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002388 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002389 MPI_VALIDATE_RET( X != NULL );
2390 MPI_VALIDATE_RET( A != NULL );
2391 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002392
Hanno Becker4bcb4912017-04-18 15:49:39 +01002393 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002394 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2397 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2398 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002400 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002401
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002402 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002403 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002404 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002405 goto cleanup;
2406 }
2407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002408 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2409 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2410 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2411 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002413 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2414 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2415 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2416 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002417
2418 do
2419 {
2420 while( ( TU.p[0] & 1 ) == 0 )
2421 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002422 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002423
2424 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2425 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002426 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2427 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002428 }
2429
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002430 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2431 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002432 }
2433
2434 while( ( TV.p[0] & 1 ) == 0 )
2435 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002436 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002437
2438 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2439 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2441 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002442 }
2443
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002444 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2445 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002446 }
2447
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002448 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002449 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002450 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2451 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2452 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002453 }
2454 else
2455 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002456 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2457 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2458 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002459 }
2460 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002461 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002463 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2464 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002466 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2467 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002468
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002469 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002470
2471cleanup:
2472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2474 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2475 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002476
2477 return( ret );
2478}
2479
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002480#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002481
Paul Bakker5121ce52009-01-03 21:22:43 +00002482static const int small_prime[] =
2483{
2484 3, 5, 7, 11, 13, 17, 19, 23,
2485 29, 31, 37, 41, 43, 47, 53, 59,
2486 61, 67, 71, 73, 79, 83, 89, 97,
2487 101, 103, 107, 109, 113, 127, 131, 137,
2488 139, 149, 151, 157, 163, 167, 173, 179,
2489 181, 191, 193, 197, 199, 211, 223, 227,
2490 229, 233, 239, 241, 251, 257, 263, 269,
2491 271, 277, 281, 283, 293, 307, 311, 313,
2492 317, 331, 337, 347, 349, 353, 359, 367,
2493 373, 379, 383, 389, 397, 401, 409, 419,
2494 421, 431, 433, 439, 443, 449, 457, 461,
2495 463, 467, 479, 487, 491, 499, 503, 509,
2496 521, 523, 541, 547, 557, 563, 569, 571,
2497 577, 587, 593, 599, 601, 607, 613, 617,
2498 619, 631, 641, 643, 647, 653, 659, 661,
2499 673, 677, 683, 691, 701, 709, 719, 727,
2500 733, 739, 743, 751, 757, 761, 769, 773,
2501 787, 797, 809, 811, 821, 823, 827, 829,
2502 839, 853, 857, 859, 863, 877, 881, 883,
2503 887, 907, 911, 919, 929, 937, 941, 947,
2504 953, 967, 971, 977, 983, 991, 997, -103
2505};
2506
2507/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002508 * Small divisors test (X must be positive)
2509 *
2510 * Return values:
2511 * 0: no small factor (possible prime, more tests needed)
2512 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002513 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002514 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002515 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002516static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002517{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002518 int ret = 0;
2519 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002520 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002521
Paul Bakker5121ce52009-01-03 21:22:43 +00002522 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002523 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002524
2525 for( i = 0; small_prime[i] > 0; i++ )
2526 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002527 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002528 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002529
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002530 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002531
2532 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002533 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002534 }
2535
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002536cleanup:
2537 return( ret );
2538}
2539
2540/*
2541 * Miller-Rabin pseudo-primality test (HAC 4.24)
2542 */
Janos Follathda31fa12018-09-03 14:45:23 +01002543static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002544 int (*f_rng)(void *, unsigned char *, size_t),
2545 void *p_rng )
2546{
Pascal Junodb99183d2015-03-11 16:49:45 +01002547 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002548 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002549 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002550
Hanno Becker8ce11a32018-12-19 16:18:52 +00002551 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002552 MPI_VALIDATE_RET( f_rng != NULL );
2553
2554 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2555 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002556 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002557
Paul Bakker5121ce52009-01-03 21:22:43 +00002558 /*
2559 * W = |X| - 1
2560 * R = W >> lsb( W )
2561 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2563 s = mbedtls_mpi_lsb( &W );
2564 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2565 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002566
Janos Follathda31fa12018-09-03 14:45:23 +01002567 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002568 {
2569 /*
2570 * pick a random A, 1 < A < |X| - 1
2571 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002572 count = 0;
2573 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002574 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002575
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002576 j = mbedtls_mpi_bitlen( &A );
2577 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002578 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002579 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002580 }
2581
2582 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002583 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2584 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002585 }
2586
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002587 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2588 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002589
2590 /*
2591 * A = A^R mod |X|
2592 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002593 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002594
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002595 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2596 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002597 continue;
2598
2599 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002600 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002601 {
2602 /*
2603 * A = A * A mod |X|
2604 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002605 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2606 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002607
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002608 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002609 break;
2610
2611 j++;
2612 }
2613
2614 /*
2615 * not prime if A != |X| - 1 or A == 1
2616 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002617 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2618 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002619 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002620 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002621 break;
2622 }
2623 }
2624
2625cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002626 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2627 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002628 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002629
2630 return( ret );
2631}
2632
2633/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002634 * Pseudo-primality test: small factors, then Miller-Rabin
2635 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002636int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2637 int (*f_rng)(void *, unsigned char *, size_t),
2638 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002639{
Janos Follath24eed8d2019-11-22 13:21:35 +00002640 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002641 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002642 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002643 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002644
2645 XX.s = 1;
2646 XX.n = X->n;
2647 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002648
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002649 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2650 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2651 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002652
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002653 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002654 return( 0 );
2655
2656 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2657 {
2658 if( ret == 1 )
2659 return( 0 );
2660
2661 return( ret );
2662 }
2663
Janos Follathda31fa12018-09-03 14:45:23 +01002664 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002665}
2666
Janos Follatha0b67c22018-09-18 14:48:23 +01002667#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002668/*
2669 * Pseudo-primality test, error probability 2^-80
2670 */
2671int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2672 int (*f_rng)(void *, unsigned char *, size_t),
2673 void *p_rng )
2674{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002675 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002676 MPI_VALIDATE_RET( f_rng != NULL );
2677
Janos Follatha0b67c22018-09-18 14:48:23 +01002678 /*
2679 * In the past our key generation aimed for an error rate of at most
2680 * 2^-80. Since this function is deprecated, aim for the same certainty
2681 * here as well.
2682 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002683 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002684}
Janos Follatha0b67c22018-09-18 14:48:23 +01002685#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002686
2687/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002688 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002689 *
Janos Follathf301d232018-08-14 13:34:01 +01002690 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2691 * be either 1024 bits or 1536 bits long, and flags must contain
2692 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002693 */
Janos Follath7c025a92018-08-14 11:08:41 +01002694int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002695 int (*f_rng)(void *, unsigned char *, size_t),
2696 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002697{
Jethro Beekman66689272018-02-14 19:24:10 -08002698#ifdef MBEDTLS_HAVE_INT64
2699// ceil(2^63.5)
2700#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2701#else
2702// ceil(2^31.5)
2703#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2704#endif
2705 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002706 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002707 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002708 mbedtls_mpi_uint r;
2709 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002710
Hanno Becker8ce11a32018-12-19 16:18:52 +00002711 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002712 MPI_VALIDATE_RET( f_rng != NULL );
2713
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002714 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2715 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002716
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002717 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002718
2719 n = BITS_TO_LIMBS( nbits );
2720
Janos Follathda31fa12018-09-03 14:45:23 +01002721 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2722 {
2723 /*
2724 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2725 */
2726 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2727 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2728 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2729 }
2730 else
2731 {
2732 /*
2733 * 2^-100 error probability, number of rounds computed based on HAC,
2734 * fact 4.48
2735 */
2736 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2737 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2738 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2739 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2740 }
2741
Jethro Beekman66689272018-02-14 19:24:10 -08002742 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002743 {
Jethro Beekman66689272018-02-14 19:24:10 -08002744 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2745 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2746 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2747
2748 k = n * biL;
2749 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2750 X->p[0] |= 1;
2751
Janos Follath7c025a92018-08-14 11:08:41 +01002752 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002753 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002754 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002755
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002756 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002757 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002758 }
Jethro Beekman66689272018-02-14 19:24:10 -08002759 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002760 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002761 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002762 * An necessary condition for Y and X = 2Y + 1 to be prime
2763 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2764 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002765 */
Jethro Beekman66689272018-02-14 19:24:10 -08002766
2767 X->p[0] |= 2;
2768
2769 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2770 if( r == 0 )
2771 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2772 else if( r == 1 )
2773 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2774
2775 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2776 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2777 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2778
2779 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002780 {
Jethro Beekman66689272018-02-14 19:24:10 -08002781 /*
2782 * First, check small factors for X and Y
2783 * before doing Miller-Rabin on any of them
2784 */
2785 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2786 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002787 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002788 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002789 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002790 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002791 goto cleanup;
2792
2793 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2794 goto cleanup;
2795
2796 /*
2797 * Next candidates. We want to preserve Y = (X-1) / 2 and
2798 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2799 * so up Y by 6 and X by 12.
2800 */
2801 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2802 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002803 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002804 }
2805 }
2806
2807cleanup:
2808
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002809 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002810
2811 return( ret );
2812}
2813
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002814#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002815
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002816#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002817
Paul Bakker23986e52011-04-24 08:57:21 +00002818#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002819
2820static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2821{
2822 { 693, 609, 21 },
2823 { 1764, 868, 28 },
2824 { 768454923, 542167814, 1 }
2825};
2826
Paul Bakker5121ce52009-01-03 21:22:43 +00002827/*
2828 * Checkup routine
2829 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002830int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002831{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002832 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002833 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002834
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002835 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2836 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002837
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002838 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002839 "EFE021C2645FD1DC586E69184AF4A31E" \
2840 "D5F53E93B5F123FA41680867BA110131" \
2841 "944FE7952E2517337780CB0DB80E61AA" \
2842 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2843
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002844 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002845 "B2E7EFD37075B9F03FF989C7C5051C20" \
2846 "34D2A323810251127E7BF8625A4F49A5" \
2847 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2848 "5B5C25763222FEFCCFC38B832366C29E" ) );
2849
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002850 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002851 "0066A198186C18C10B2F5ED9B522752A" \
2852 "9830B69916E535C8F047518A889A43A5" \
2853 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2854
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002855 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002856
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002857 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002858 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2859 "9E857EA95A03512E2BAE7391688D264A" \
2860 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2861 "8001B72E848A38CAE1C65F78E56ABDEF" \
2862 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2863 "ECF677152EF804370C1A305CAF3B5BF1" \
2864 "30879B56C61DE584A0F53A2447A51E" ) );
2865
2866 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002867 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002868
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002869 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002870 {
2871 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002872 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002873
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002874 ret = 1;
2875 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002876 }
2877
2878 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002879 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002880
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002881 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002882
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002883 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002884 "256567336059E52CAE22925474705F39A94" ) );
2885
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002886 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002887 "6613F26162223DF488E9CD48CC132C7A" \
2888 "0AC93C701B001B092E4E5B9F73BCD27B" \
2889 "9EE50D0657C77F374E903CDFA4C642" ) );
2890
2891 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002892 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002893
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002894 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2895 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002896 {
2897 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002898 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002899
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002900 ret = 1;
2901 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002902 }
2903
2904 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002905 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002906
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002907 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002908
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002909 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002910 "36E139AEA55215609D2816998ED020BB" \
2911 "BD96C37890F65171D948E9BC7CBAA4D9" \
2912 "325D24D6A3C12710F10A09FA08AB87" ) );
2913
2914 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002915 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002916
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002917 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002918 {
2919 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002920 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002921
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002922 ret = 1;
2923 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002924 }
2925
2926 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002927 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002928
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002929 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002930
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002931 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002932 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2933 "C3DBA76456363A10869622EAC2DD84EC" \
2934 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2935
2936 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002937 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002938
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002939 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002940 {
2941 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002942 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002943
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002944 ret = 1;
2945 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002946 }
2947
2948 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002949 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002950
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002951 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002952 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002953
Paul Bakker66d5d072014-06-17 16:39:18 +02002954 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002955 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002956 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2957 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002958
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002959 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002960
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002961 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002962 {
2963 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002964 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002965
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002966 ret = 1;
2967 goto cleanup;
2968 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002969 }
2970
2971 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002972 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002973
Paul Bakker5121ce52009-01-03 21:22:43 +00002974cleanup:
2975
2976 if( ret != 0 && verbose != 0 )
Kenneth Soerensen518d4352020-04-01 17:22:45 +02002977 mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002978
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002979 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2980 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002981
2982 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002983 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002984
2985 return( ret );
2986}
2987
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002988#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002989
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002990#endif /* MBEDTLS_BIGNUM_C */