blob: f42b97650fdf28885ca7dc47c597bd68773a9c8b [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
Bence Szépkútif744bd72020-06-05 13:02:18 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +020012 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000024 *
Bence Szépkútif744bd72020-06-05 13:02:18 +020025 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
45 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000046 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000047 */
Simon Butcher15b15d12015-11-26 19:35:03 +000048
Paul Bakker5121ce52009-01-03 21:22:43 +000049/*
Simon Butcher15b15d12015-11-26 19:35:03 +000050 * The following sources were referenced in the design of this Multi-precision
51 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000052 *
Simon Butcher15b15d12015-11-26 19:35:03 +000053 * [1] Handbook of Applied Cryptography - 1997
54 * Menezes, van Oorschot and Vanstone
55 *
56 * [2] Multi-Precision Math
57 * Tom St Denis
58 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
59 *
60 * [3] GNU Multi-Precision Arithmetic Library
61 * https://gmplib.org/manual/index.html
62 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000063 */
Paul Bakker5121ce52009-01-03 21:22:43 +000064
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020065#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000066#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020067#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020068#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020069#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000070
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000072
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000073#include "mbedtls/bignum.h"
74#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050075#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000076
Rich Evans00ab4702015-02-06 13:43:58 +000077#include <string.h>
78
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020079#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000080#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020081#else
Rich Evans00ab4702015-02-06 13:43:58 +000082#include <stdio.h>
83#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020085#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020086#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020087#endif
88
Hanno Becker73d7d792018-12-11 10:35:51 +000089#define MPI_VALIDATE_RET( cond ) \
90 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
91#define MPI_VALIDATE( cond ) \
92 MBEDTLS_INTERNAL_VALIDATE( cond )
93
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020094#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000095#define biL (ciL << 3) /* bits in limb */
96#define biH (ciL << 2) /* half limb size */
97
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010098#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
99
Paul Bakker5121ce52009-01-03 21:22:43 +0000100/*
101 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200102 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +0000103 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200104#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
105#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +0000106
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500107/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -0500108static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
109{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500110 mbedtls_platform_zeroize( v, ciL * n );
111}
112
Paul Bakker5121ce52009-01-03 21:22:43 +0000113/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000114 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000115 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000117{
Hanno Becker73d7d792018-12-11 10:35:51 +0000118 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000119
Paul Bakker6c591fa2011-05-05 11:49:20 +0000120 X->s = 1;
121 X->n = 0;
122 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000123}
124
125/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000126 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000127 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000129{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000130 if( X == NULL )
131 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000132
Paul Bakker6c591fa2011-05-05 11:49:20 +0000133 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000134 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200135 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000137 }
138
Paul Bakker6c591fa2011-05-05 11:49:20 +0000139 X->s = 1;
140 X->n = 0;
141 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000142}
143
144/*
145 * Enlarge to the specified number of limbs
146 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200147int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000148{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000150 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200152 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200153 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000154
Paul Bakker5121ce52009-01-03 21:22:43 +0000155 if( X->n < nblimbs )
156 {
Simon Butcher29176892016-05-20 00:19:09 +0100157 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200158 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000159
Paul Bakker5121ce52009-01-03 21:22:43 +0000160 if( X->p != NULL )
161 {
162 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200163 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200164 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000165 }
166
167 X->n = nblimbs;
168 X->p = p;
169 }
170
171 return( 0 );
172}
173
174/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175 * Resize down as much as possible,
176 * while keeping at least the specified number of limbs
177 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200178int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100179{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100181 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000182 MPI_VALIDATE_RET( X != NULL );
183
184 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
185 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100186
Gilles Peskine27c15c72020-01-20 21:17:43 +0100187 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100188 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200189 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine56427c22020-01-21 13:59:51 +0100190 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100191
192 for( i = X->n - 1; i > 0; i-- )
193 if( X->p[i] != 0 )
194 break;
195 i++;
196
197 if( i < nblimbs )
198 i = nblimbs;
199
Simon Butcher29176892016-05-20 00:19:09 +0100200 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200201 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100202
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100203 if( X->p != NULL )
204 {
205 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200206 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100208 }
209
210 X->n = i;
211 X->p = p;
212
213 return( 0 );
214}
215
216/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000217 * Copy the contents of Y into X
218 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000220{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100221 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000222 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000223 MPI_VALIDATE_RET( X != NULL );
224 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000225
226 if( X == Y )
227 return( 0 );
228
Gilles Peskine3e9f5222020-01-20 21:12:50 +0100229 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200230 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200231 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200232 return( 0 );
233 }
234
Paul Bakker5121ce52009-01-03 21:22:43 +0000235 for( i = Y->n - 1; i > 0; i-- )
236 if( Y->p[i] != 0 )
237 break;
238 i++;
239
240 X->s = Y->s;
241
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100242 if( X->n < i )
243 {
244 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
245 }
246 else
247 {
248 memset( X->p + i, 0, ( X->n - i ) * ciL );
249 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000250
Paul Bakker5121ce52009-01-03 21:22:43 +0000251 memcpy( X->p, Y->p, i * ciL );
252
253cleanup:
254
255 return( ret );
256}
257
258/*
259 * Swap the contents of X and Y
260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000262{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000264 MPI_VALIDATE( X != NULL );
265 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267 memcpy( &T, X, sizeof( mbedtls_mpi ) );
268 memcpy( X, Y, sizeof( mbedtls_mpi ) );
269 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000270}
271
272/*
Gilles Peskinec81c5882020-06-04 19:14:58 +0200273 * Conditionally assign dest = src, without leaking information
274 * about whether the assignment was made or not.
275 * dest and src must be arrays of limbs of size n.
276 * assign must be 0 or 1.
277 */
278static void mpi_safe_cond_assign( size_t n,
279 mbedtls_mpi_uint *dest,
280 const mbedtls_mpi_uint *src,
281 unsigned char assign )
282{
283 size_t i;
284 for( i = 0; i < n; i++ )
285 dest[i] = dest[i] * ( 1 - assign ) + src[i] * assign;
286}
287
288/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100289 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100290 * about whether the assignment was made or not.
291 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100292 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100294{
295 int ret = 0;
296 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000297 MPI_VALIDATE_RET( X != NULL );
298 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100299
Pascal Junodb99183d2015-03-11 16:49:45 +0100300 /* make sure assign is 0 or 1 in a time-constant manner */
301 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100302
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200303 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100304
Paul Bakker66d5d072014-06-17 16:39:18 +0200305 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100306
Gilles Peskinec81c5882020-06-04 19:14:58 +0200307 mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100308
Gilles Peskinec81c5882020-06-04 19:14:58 +0200309 for( i = Y->n; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200310 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100311
312cleanup:
313 return( ret );
314}
315
316/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100317 * Conditionally swap X and Y, without leaking information
318 * about whether the swap was made or not.
319 * Here it is not ok to simply swap the pointers, which whould lead to
320 * different memory access patterns when X and Y are used afterwards.
321 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200322int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100323{
324 int ret, s;
325 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000327 MPI_VALIDATE_RET( X != NULL );
328 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100329
330 if( X == Y )
331 return( 0 );
332
Pascal Junodb99183d2015-03-11 16:49:45 +0100333 /* make sure swap is 0 or 1 in a time-constant manner */
334 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
337 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100338
339 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200340 X->s = X->s * ( 1 - swap ) + Y->s * swap;
341 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100342
343
344 for( i = 0; i < X->n; i++ )
345 {
346 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200347 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
348 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100349 }
350
351cleanup:
352 return( ret );
353}
354
355/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000356 * Set value from integer
357 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200358int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000359{
360 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +0000361 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000362
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200363 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000364 memset( X->p, 0, X->n * ciL );
365
366 X->p[0] = ( z < 0 ) ? -z : z;
367 X->s = ( z < 0 ) ? -1 : 1;
368
369cleanup:
370
371 return( ret );
372}
373
374/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000375 * Get a specific bit
376 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200377int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000378{
Hanno Becker73d7d792018-12-11 10:35:51 +0000379 MPI_VALIDATE_RET( X != NULL );
380
Paul Bakker2f5947e2011-05-18 15:47:11 +0000381 if( X->n * biL <= pos )
382 return( 0 );
383
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200384 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000385}
386
Gilles Peskine11cdb052018-11-20 16:47:47 +0100387/* Get a specific byte, without range checks. */
388#define GET_BYTE( X, i ) \
389 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
390
Paul Bakker2f5947e2011-05-18 15:47:11 +0000391/*
392 * Set a bit to a specific value of 0 or 1
393 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000395{
396 int ret = 0;
397 size_t off = pos / biL;
398 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000399 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000400
401 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200402 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200403
Paul Bakker2f5947e2011-05-18 15:47:11 +0000404 if( X->n * biL <= pos )
405 {
406 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200407 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000410 }
411
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200412 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
413 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000414
415cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200416
Paul Bakker2f5947e2011-05-18 15:47:11 +0000417 return( ret );
418}
419
420/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200421 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000422 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200423size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000424{
Paul Bakker23986e52011-04-24 08:57:21 +0000425 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000426 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000427
428 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000429 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000430 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
431 return( count );
432
433 return( 0 );
434}
435
436/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000437 * Count leading zero bits in a given integer
438 */
439static size_t mbedtls_clz( const mbedtls_mpi_uint x )
440{
441 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100442 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000443
444 for( j = 0; j < biL; j++ )
445 {
446 if( x & mask ) break;
447
448 mask >>= 1;
449 }
450
451 return j;
452}
453
454/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200455 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000456 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200457size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000458{
Paul Bakker23986e52011-04-24 08:57:21 +0000459 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000460
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200461 if( X->n == 0 )
462 return( 0 );
463
Paul Bakker5121ce52009-01-03 21:22:43 +0000464 for( i = X->n - 1; i > 0; i-- )
465 if( X->p[i] != 0 )
466 break;
467
Simon Butcher15b15d12015-11-26 19:35:03 +0000468 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
Paul Bakker23986e52011-04-24 08:57:21 +0000470 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000471}
472
473/*
474 * Return the total size in bytes
475 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000477{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200478 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000479}
480
481/*
482 * Convert an ASCII character to digit value
483 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000485{
486 *d = 255;
487
488 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
489 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
490 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 if( *d >= (mbedtls_mpi_uint) radix )
493 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494
495 return( 0 );
496}
497
498/*
499 * Import from an ASCII string
500 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200501int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000502{
Paul Bakker23986e52011-04-24 08:57:21 +0000503 int ret;
504 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200505 mbedtls_mpi_uint d;
506 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000507 MPI_VALIDATE_RET( X != NULL );
508 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000509
510 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000511 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000514
Paul Bakkerff60ee62010-03-16 21:09:09 +0000515 slen = strlen( s );
516
Paul Bakker5121ce52009-01-03 21:22:43 +0000517 if( radix == 16 )
518 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100519 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200520 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
521
Paul Bakkerff60ee62010-03-16 21:09:09 +0000522 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
525 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000526
Paul Bakker23986e52011-04-24 08:57:21 +0000527 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000528 {
Paul Bakker23986e52011-04-24 08:57:21 +0000529 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000530 {
531 X->s = -1;
532 break;
533 }
534
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200535 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200536 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000537 }
538 }
539 else
540 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200541 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000542
Paul Bakkerff60ee62010-03-16 21:09:09 +0000543 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000544 {
545 if( i == 0 && s[i] == '-' )
546 {
547 X->s = -1;
548 continue;
549 }
550
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200551 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
552 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000553
554 if( X->s == 1 )
555 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200556 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000557 }
558 else
559 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200560 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000561 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000562 }
563 }
564
565cleanup:
566
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000568
569 return( ret );
570}
571
572/*
Ron Eldora16fa292018-11-20 14:07:01 +0200573 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000574 */
Ron Eldora16fa292018-11-20 14:07:01 +0200575static int mpi_write_hlp( mbedtls_mpi *X, int radix,
576 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000577{
578 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200579 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200580 size_t length = 0;
581 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000582
Ron Eldora16fa292018-11-20 14:07:01 +0200583 do
584 {
585 if( length >= buflen )
586 {
587 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
588 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000589
Ron Eldora16fa292018-11-20 14:07:01 +0200590 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
591 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
592 /*
593 * Write the residue in the current position, as an ASCII character.
594 */
595 if( r < 0xA )
596 *(--p_end) = (char)( '0' + r );
597 else
598 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
Ron Eldora16fa292018-11-20 14:07:01 +0200600 length++;
601 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000602
Ron Eldora16fa292018-11-20 14:07:01 +0200603 memmove( *p, p_end, length );
604 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000605
606cleanup:
607
608 return( ret );
609}
610
611/*
612 * Export into an ASCII string
613 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100614int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
615 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000616{
Paul Bakker23986e52011-04-24 08:57:21 +0000617 int ret = 0;
618 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000619 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000621 MPI_VALIDATE_RET( X != NULL );
622 MPI_VALIDATE_RET( olen != NULL );
623 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000624
625 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000626 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000627
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000628 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
629 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
630 * `n`. If radix > 4, this might be a strict
631 * overapproximation of the number of
632 * radix-adic digits needed to present `n`. */
633 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
634 * present `n`. */
635
Janos Follath870ed002019-03-06 13:43:02 +0000636 n += 1; /* Terminating null byte */
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000637 n += 1; /* Compensate for the divisions above, which round down `n`
638 * in case it's not even. */
639 n += 1; /* Potential '-'-sign. */
640 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
641 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000642
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100643 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000644 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100645 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200646 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000647 }
648
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100649 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000651
652 if( X->s == -1 )
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000653 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000654 *p++ = '-';
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000655 buflen--;
656 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000657
658 if( radix == 16 )
659 {
Paul Bakker23986e52011-04-24 08:57:21 +0000660 int c;
661 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000662
Paul Bakker23986e52011-04-24 08:57:21 +0000663 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000664 {
Paul Bakker23986e52011-04-24 08:57:21 +0000665 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000666 {
Paul Bakker23986e52011-04-24 08:57:21 +0000667 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000668
Paul Bakker6c343d72014-07-10 14:36:19 +0200669 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000670 continue;
671
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000672 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000673 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000674 k = 1;
675 }
676 }
677 }
678 else
679 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000681
682 if( T.s == -1 )
683 T.s = 1;
684
Ron Eldora16fa292018-11-20 14:07:01 +0200685 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000686 }
687
688 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100689 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000690
691cleanup:
692
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200693 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000694
695 return( ret );
696}
697
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000699/*
700 * Read X from an opened file
701 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200702int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000703{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200704 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000705 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000706 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000707 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000708 * Buffer should have space for (short) label and decimal formatted MPI,
709 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000710 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200711 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000712
Hanno Becker73d7d792018-12-11 10:35:51 +0000713 MPI_VALIDATE_RET( X != NULL );
714 MPI_VALIDATE_RET( fin != NULL );
715
716 if( radix < 2 || radix > 16 )
717 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
718
Paul Bakker5121ce52009-01-03 21:22:43 +0000719 memset( s, 0, sizeof( s ) );
720 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000722
723 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000724 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200725 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000726
Hanno Beckerb2034b72017-04-26 11:46:46 +0100727 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
728 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000729
730 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100731 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000732 if( mpi_get_digit( &d, radix, *p ) != 0 )
733 break;
734
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200735 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000736}
737
738/*
739 * Write X into an opened file (or stdout if fout == NULL)
740 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000742{
Paul Bakker23986e52011-04-24 08:57:21 +0000743 int ret;
744 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000745 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000746 * Buffer should have space for (short) label and decimal formatted MPI,
747 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000748 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200749 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000750 MPI_VALIDATE_RET( X != NULL );
751
752 if( radix < 2 || radix > 16 )
753 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000754
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100755 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000756
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100757 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000758
759 if( p == NULL ) p = "";
760
761 plen = strlen( p );
762 slen = strlen( s );
763 s[slen++] = '\r';
764 s[slen++] = '\n';
765
766 if( fout != NULL )
767 {
768 if( fwrite( p, 1, plen, fout ) != plen ||
769 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200770 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000771 }
772 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200773 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000774
775cleanup:
776
777 return( ret );
778}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200779#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000780
Hanno Beckerda1655a2017-10-18 14:21:44 +0100781
782/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
783 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000784
785static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
786{
787 uint8_t i;
Hanno Becker92c98932019-05-01 17:09:11 +0100788 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000789 mbedtls_mpi_uint tmp = 0;
Hanno Becker92c98932019-05-01 17:09:11 +0100790
791 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
792 {
793 tmp <<= CHAR_BIT;
794 tmp |= (mbedtls_mpi_uint) *x_ptr;
795 }
796
Hanno Beckerf8720072018-11-08 11:53:49 +0000797 return( tmp );
798}
799
800static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
801{
802#if defined(__BYTE_ORDER__)
803
804/* Nothing to do on bigendian systems. */
805#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
806 return( x );
807#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
808
809#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
810
811/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000812#if defined(__GNUC__) && defined(__GNUC_PREREQ)
813#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000814#define have_bswap
815#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000816#endif
817
818#if defined(__clang__) && defined(__has_builtin)
819#if __has_builtin(__builtin_bswap32) && \
820 __has_builtin(__builtin_bswap64)
821#define have_bswap
822#endif
823#endif
824
Hanno Beckerf8720072018-11-08 11:53:49 +0000825#if defined(have_bswap)
826 /* The compiler is hopefully able to statically evaluate this! */
827 switch( sizeof(mbedtls_mpi_uint) )
828 {
829 case 4:
830 return( __builtin_bswap32(x) );
831 case 8:
832 return( __builtin_bswap64(x) );
833 }
834#endif
835#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
836#endif /* __BYTE_ORDER__ */
837
838 /* Fall back to C-based reordering if we don't know the byte order
839 * or we couldn't use a compiler-specific builtin. */
840 return( mpi_uint_bigendian_to_host_c( x ) );
841}
842
Hanno Becker2be8a552018-10-25 12:40:09 +0100843static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100844{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100845 mbedtls_mpi_uint *cur_limb_left;
846 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100847 if( limbs == 0 )
848 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100849
850 /*
851 * Traverse limbs and
852 * - adapt byte-order in each limb
853 * - swap the limbs themselves.
854 * For that, simultaneously traverse the limbs from left to right
855 * and from right to left, as long as the left index is not bigger
856 * than the right index (it's not a problem if limbs is odd and the
857 * indices coincide in the last iteration).
858 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100859 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
860 cur_limb_left <= cur_limb_right;
861 cur_limb_left++, cur_limb_right-- )
862 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000863 mbedtls_mpi_uint tmp;
864 /* Note that if cur_limb_left == cur_limb_right,
865 * this code effectively swaps the bytes only once. */
866 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
867 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
868 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100869 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100870}
871
Paul Bakker5121ce52009-01-03 21:22:43 +0000872/*
873 * Import X from unsigned binary data, big endian
874 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200875int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000876{
Paul Bakker23986e52011-04-24 08:57:21 +0000877 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100878 size_t const limbs = CHARS_TO_LIMBS( buflen );
879 size_t const overhead = ( limbs * ciL ) - buflen;
880 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000881
Hanno Becker8ce11a32018-12-19 16:18:52 +0000882 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000883 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
884
Hanno Becker073c1992017-10-17 15:17:27 +0100885 /* Ensure that target MPI has exactly the necessary number of limbs */
886 if( X->n != limbs )
887 {
888 mbedtls_mpi_free( X );
889 mbedtls_mpi_init( X );
890 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
891 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200892 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000893
Hanno Becker0e810b92019-01-03 17:13:11 +0000894 /* Avoid calling `memcpy` with NULL source argument,
895 * even if buflen is 0. */
896 if( buf != NULL )
897 {
898 Xp = (unsigned char*) X->p;
899 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100900
Hanno Becker0e810b92019-01-03 17:13:11 +0000901 mpi_bigendian_to_host( X->p, limbs );
902 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000903
904cleanup:
905
906 return( ret );
907}
908
909/*
910 * Export X into unsigned binary data, big endian
911 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100912int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
913 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000914{
Hanno Becker73d7d792018-12-11 10:35:51 +0000915 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100916 size_t bytes_to_copy;
917 unsigned char *p;
918 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000919
Hanno Becker73d7d792018-12-11 10:35:51 +0000920 MPI_VALIDATE_RET( X != NULL );
921 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
922
923 stored_bytes = X->n * ciL;
924
Gilles Peskine11cdb052018-11-20 16:47:47 +0100925 if( stored_bytes < buflen )
926 {
927 /* There is enough space in the output buffer. Write initial
928 * null bytes and record the position at which to start
929 * writing the significant bytes. In this case, the execution
930 * trace of this function does not depend on the value of the
931 * number. */
932 bytes_to_copy = stored_bytes;
933 p = buf + buflen - stored_bytes;
934 memset( buf, 0, buflen - stored_bytes );
935 }
936 else
937 {
938 /* The output buffer is smaller than the allocated size of X.
939 * However X may fit if its leading bytes are zero. */
940 bytes_to_copy = buflen;
941 p = buf;
942 for( i = bytes_to_copy; i < stored_bytes; i++ )
943 {
944 if( GET_BYTE( X, i ) != 0 )
945 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
946 }
947 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000948
Gilles Peskine11cdb052018-11-20 16:47:47 +0100949 for( i = 0; i < bytes_to_copy; i++ )
950 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000951
952 return( 0 );
953}
954
955/*
956 * Left-shift: X <<= count
957 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200958int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000959{
Paul Bakker23986e52011-04-24 08:57:21 +0000960 int ret;
961 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200962 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000963 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000964
965 v0 = count / (biL );
966 t1 = count & (biL - 1);
967
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200968 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000969
Paul Bakkerf9688572011-05-05 10:00:45 +0000970 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200971 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000972
973 ret = 0;
974
975 /*
976 * shift by count / limb_size
977 */
978 if( v0 > 0 )
979 {
Paul Bakker23986e52011-04-24 08:57:21 +0000980 for( i = X->n; i > v0; i-- )
981 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000982
Paul Bakker23986e52011-04-24 08:57:21 +0000983 for( ; i > 0; i-- )
984 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000985 }
986
987 /*
988 * shift by count % limb_size
989 */
990 if( t1 > 0 )
991 {
992 for( i = v0; i < X->n; i++ )
993 {
994 r1 = X->p[i] >> (biL - t1);
995 X->p[i] <<= t1;
996 X->p[i] |= r0;
997 r0 = r1;
998 }
999 }
1000
1001cleanup:
1002
1003 return( ret );
1004}
1005
1006/*
1007 * Right-shift: X >>= count
1008 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001009int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001010{
Paul Bakker23986e52011-04-24 08:57:21 +00001011 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001012 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001013 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001014
1015 v0 = count / biL;
1016 v1 = count & (biL - 1);
1017
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001018 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001020
Paul Bakker5121ce52009-01-03 21:22:43 +00001021 /*
1022 * shift by count / limb_size
1023 */
1024 if( v0 > 0 )
1025 {
1026 for( i = 0; i < X->n - v0; i++ )
1027 X->p[i] = X->p[i + v0];
1028
1029 for( ; i < X->n; i++ )
1030 X->p[i] = 0;
1031 }
1032
1033 /*
1034 * shift by count % limb_size
1035 */
1036 if( v1 > 0 )
1037 {
Paul Bakker23986e52011-04-24 08:57:21 +00001038 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001039 {
Paul Bakker23986e52011-04-24 08:57:21 +00001040 r1 = X->p[i - 1] << (biL - v1);
1041 X->p[i - 1] >>= v1;
1042 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001043 r0 = r1;
1044 }
1045 }
1046
1047 return( 0 );
1048}
1049
1050/*
1051 * Compare unsigned values
1052 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001053int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001054{
Paul Bakker23986e52011-04-24 08:57:21 +00001055 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001056 MPI_VALIDATE_RET( X != NULL );
1057 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001058
Paul Bakker23986e52011-04-24 08:57:21 +00001059 for( i = X->n; i > 0; i-- )
1060 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001061 break;
1062
Paul Bakker23986e52011-04-24 08:57:21 +00001063 for( j = Y->n; j > 0; j-- )
1064 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001065 break;
1066
Paul Bakker23986e52011-04-24 08:57:21 +00001067 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001068 return( 0 );
1069
1070 if( i > j ) return( 1 );
1071 if( j > i ) return( -1 );
1072
Paul Bakker23986e52011-04-24 08:57:21 +00001073 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001074 {
Paul Bakker23986e52011-04-24 08:57:21 +00001075 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1076 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001077 }
1078
1079 return( 0 );
1080}
1081
1082/*
1083 * Compare signed values
1084 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001085int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001086{
Paul Bakker23986e52011-04-24 08:57:21 +00001087 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001088 MPI_VALIDATE_RET( X != NULL );
1089 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001090
Paul Bakker23986e52011-04-24 08:57:21 +00001091 for( i = X->n; i > 0; i-- )
1092 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001093 break;
1094
Paul Bakker23986e52011-04-24 08:57:21 +00001095 for( j = Y->n; j > 0; j-- )
1096 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001097 break;
1098
Paul Bakker23986e52011-04-24 08:57:21 +00001099 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001100 return( 0 );
1101
1102 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001103 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001104
1105 if( X->s > 0 && Y->s < 0 ) return( 1 );
1106 if( Y->s > 0 && X->s < 0 ) return( -1 );
1107
Paul Bakker23986e52011-04-24 08:57:21 +00001108 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001109 {
Paul Bakker23986e52011-04-24 08:57:21 +00001110 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1111 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001112 }
1113
1114 return( 0 );
1115}
1116
Janos Follath45ec9902019-10-14 09:09:32 +01001117/** Decide if an integer is less than the other, without branches.
1118 *
1119 * \param x First integer.
1120 * \param y Second integer.
1121 *
1122 * \return 1 if \p x is less than \p y, 0 otherwise
1123 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001124static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1125 const mbedtls_mpi_uint y )
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001126{
1127 mbedtls_mpi_uint ret;
1128 mbedtls_mpi_uint cond;
1129
1130 /*
1131 * Check if the most significant bits (MSB) of the operands are different.
1132 */
1133 cond = ( x ^ y );
1134 /*
1135 * If the MSB are the same then the difference x-y will be negative (and
1136 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1137 */
1138 ret = ( x - y ) & ~cond;
1139 /*
1140 * If the MSB are different, then the operand with the MSB of 1 is the
1141 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1142 * the MSB of y is 0.)
1143 */
1144 ret |= y & cond;
1145
1146
Janos Follath7a34bcf2019-10-14 08:59:14 +01001147 ret = ret >> ( biL - 1 );
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001148
Janos Follath359a01e2019-10-29 15:08:46 +00001149 return (unsigned) ret;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001150}
1151
1152/*
1153 * Compare signed values in constant time
1154 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001155int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1156 unsigned *ret )
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001157{
1158 size_t i;
Janos Follathbd87a592019-10-28 12:23:18 +00001159 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001160 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001161
1162 MPI_VALIDATE_RET( X != NULL );
1163 MPI_VALIDATE_RET( Y != NULL );
1164 MPI_VALIDATE_RET( ret != NULL );
1165
1166 if( X->n != Y->n )
1167 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1168
1169 /*
Janos Follath58525182019-10-28 12:12:15 +00001170 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1171 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001172 */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001173 X_is_negative = ( X->s & 2 ) >> 1;
1174 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follath867a3ab2019-10-11 14:21:53 +01001175
1176 /*
1177 * If the signs are different, then the positive operand is the bigger.
Janos Follath1f21c1d2019-10-28 12:31:34 +00001178 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1179 * is false if X is positive (X_is_negative == 0).
Janos Follath867a3ab2019-10-11 14:21:53 +01001180 */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001181 cond = ( X_is_negative ^ Y_is_negative );
1182 *ret = cond & X_is_negative;
Janos Follath867a3ab2019-10-11 14:21:53 +01001183
1184 /*
Janos Follathbd87a592019-10-28 12:23:18 +00001185 * This is a constant-time function. We might have the result, but we still
Janos Follath867a3ab2019-10-11 14:21:53 +01001186 * need to go through the loop. Record if we have the result already.
1187 */
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001188 done = cond;
1189
1190 for( i = X->n; i > 0; i-- )
1191 {
1192 /*
Janos Follathe25f1ee2019-11-05 12:24:52 +00001193 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1194 * X and Y are negative.
Janos Follath867a3ab2019-10-11 14:21:53 +01001195 *
1196 * Again even if we can make a decision, we just mark the result and
1197 * the fact that we are done and continue looping.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001198 */
Janos Follathe25f1ee2019-11-05 12:24:52 +00001199 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1200 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathfbe4c942019-10-28 12:37:21 +00001201 done |= cond;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001202
1203 /*
Janos Follathe25f1ee2019-11-05 12:24:52 +00001204 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1205 * X and Y are positive.
Janos Follath867a3ab2019-10-11 14:21:53 +01001206 *
1207 * Again even if we can make a decision, we just mark the result and
1208 * the fact that we are done and continue looping.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001209 */
Janos Follathe25f1ee2019-11-05 12:24:52 +00001210 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1211 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathfbe4c942019-10-28 12:37:21 +00001212 done |= cond;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001213 }
1214
1215 return( 0 );
1216}
1217
Paul Bakker5121ce52009-01-03 21:22:43 +00001218/*
1219 * Compare signed values
1220 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001221int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001222{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001223 mbedtls_mpi Y;
1224 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001225 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001226
1227 *p = ( z < 0 ) ? -z : z;
1228 Y.s = ( z < 0 ) ? -1 : 1;
1229 Y.n = 1;
1230 Y.p = p;
1231
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001232 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001233}
1234
1235/*
1236 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1237 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001238int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001239{
Paul Bakker23986e52011-04-24 08:57:21 +00001240 int ret;
1241 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001242 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001243 MPI_VALIDATE_RET( X != NULL );
1244 MPI_VALIDATE_RET( A != NULL );
1245 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001246
1247 if( X == B )
1248 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001249 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001250 }
1251
1252 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001253 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001254
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001255 /*
1256 * X should always be positive as a result of unsigned additions.
1257 */
1258 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001259
Paul Bakker23986e52011-04-24 08:57:21 +00001260 for( j = B->n; j > 0; j-- )
1261 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001262 break;
1263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001264 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001265
1266 o = B->p; p = X->p; c = 0;
1267
Janos Follath6c922682015-10-30 17:43:11 +01001268 /*
1269 * tmp is used because it might happen that p == o
1270 */
Paul Bakker23986e52011-04-24 08:57:21 +00001271 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001272 {
Janos Follath6c922682015-10-30 17:43:11 +01001273 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001274 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001275 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001276 }
1277
1278 while( c != 0 )
1279 {
1280 if( i >= X->n )
1281 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001282 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001283 p = X->p + i;
1284 }
1285
Paul Bakker2d319fd2012-09-16 21:34:26 +00001286 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001287 }
1288
1289cleanup:
1290
1291 return( ret );
1292}
1293
Gilles Peskinede719d52020-06-09 10:39:38 +02001294/**
Gilles Peskine36acd542020-06-08 21:58:22 +02001295 * Helper for mbedtls_mpi subtraction.
1296 *
1297 * Calculate d - s where d and s have the same size.
1298 * This function operates modulo (2^ciL)^n and returns the carry
1299 * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise).
1300 *
1301 * \param n Number of limbs of \p d and \p s.
1302 * \param[in,out] d On input, the left operand.
1303 * On output, the result of the subtraction:
Gilles Peskinede719d52020-06-09 10:39:38 +02001304 * \param[in] s The right operand.
Gilles Peskine36acd542020-06-08 21:58:22 +02001305 *
1306 * \return 1 if `d < s`.
1307 * 0 if `d >= s`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001308 */
Gilles Peskine36acd542020-06-08 21:58:22 +02001309static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1310 mbedtls_mpi_uint *d,
1311 const mbedtls_mpi_uint *s )
Paul Bakker5121ce52009-01-03 21:22:43 +00001312{
Paul Bakker23986e52011-04-24 08:57:21 +00001313 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001314 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001315
1316 for( i = c = 0; i < n; i++, s++, d++ )
1317 {
1318 z = ( *d < c ); *d -= c;
1319 c = ( *d < *s ) + z; *d -= *s;
1320 }
1321
Gilles Peskine36acd542020-06-08 21:58:22 +02001322 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001323}
1324
1325/*
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001326 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001327 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001328int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001329{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001330 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001331 int ret;
1332 size_t n;
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001333 mbedtls_mpi_uint carry;
Hanno Becker73d7d792018-12-11 10:35:51 +00001334 MPI_VALIDATE_RET( X != NULL );
1335 MPI_VALIDATE_RET( A != NULL );
1336 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001338 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001339
1340 if( X == B )
1341 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001342 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001343 B = &TB;
1344 }
1345
1346 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001347 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001348
Paul Bakker1ef7a532009-06-20 10:50:55 +00001349 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001350 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001351 */
1352 X->s = 1;
1353
Paul Bakker5121ce52009-01-03 21:22:43 +00001354 ret = 0;
1355
Paul Bakker23986e52011-04-24 08:57:21 +00001356 for( n = B->n; n > 0; n-- )
1357 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001358 break;
1359
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001360 carry = mpi_sub_hlp( n, X->p, B->p );
1361 if( carry != 0 )
Gilles Peskine36acd542020-06-08 21:58:22 +02001362 {
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001363 /* Propagate the carry to the first nonzero limb of X. */
1364 for( ; n < X->n && X->p[n] == 0; n++ )
1365 --X->p[n];
1366 /* If we ran out of space for the carry, it means that the result
1367 * is negative. */
1368 if( n == X->n )
1369 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
1370 --X->p[n];
Gilles Peskine36acd542020-06-08 21:58:22 +02001371 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001372
1373cleanup:
1374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001375 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001376
1377 return( ret );
1378}
1379
1380/*
1381 * Signed addition: X = A + B
1382 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001383int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001384{
Hanno Becker73d7d792018-12-11 10:35:51 +00001385 int ret, s;
1386 MPI_VALIDATE_RET( X != NULL );
1387 MPI_VALIDATE_RET( A != NULL );
1388 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001389
Hanno Becker73d7d792018-12-11 10:35:51 +00001390 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001391 if( A->s * B->s < 0 )
1392 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001393 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001394 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001395 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001396 X->s = s;
1397 }
1398 else
1399 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001401 X->s = -s;
1402 }
1403 }
1404 else
1405 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001407 X->s = s;
1408 }
1409
1410cleanup:
1411
1412 return( ret );
1413}
1414
1415/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001416 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001417 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001418int mbedtls_mpi_sub_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/*
1451 * Signed addition: X = A + b
1452 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001453int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001454{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001455 mbedtls_mpi _B;
1456 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001457 MPI_VALIDATE_RET( X != NULL );
1458 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001459
1460 p[0] = ( b < 0 ) ? -b : b;
1461 _B.s = ( b < 0 ) ? -1 : 1;
1462 _B.n = 1;
1463 _B.p = p;
1464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001465 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001466}
1467
1468/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001469 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001470 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001472{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001473 mbedtls_mpi _B;
1474 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001475 MPI_VALIDATE_RET( X != NULL );
1476 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001477
1478 p[0] = ( b < 0 ) ? -b : b;
1479 _B.s = ( b < 0 ) ? -1 : 1;
1480 _B.n = 1;
1481 _B.p = p;
1482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001483 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001484}
1485
1486/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001487 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001488 */
1489static
1490#if defined(__APPLE__) && defined(__arm__)
1491/*
1492 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1493 * appears to need this to prevent bad ARM code generation at -O3.
1494 */
1495__attribute__ ((noinline))
1496#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001497void 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 +00001498{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001499 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001500
1501#if defined(MULADDC_HUIT)
1502 for( ; i >= 8; i -= 8 )
1503 {
1504 MULADDC_INIT
1505 MULADDC_HUIT
1506 MULADDC_STOP
1507 }
1508
1509 for( ; i > 0; i-- )
1510 {
1511 MULADDC_INIT
1512 MULADDC_CORE
1513 MULADDC_STOP
1514 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001515#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001516 for( ; i >= 16; i -= 16 )
1517 {
1518 MULADDC_INIT
1519 MULADDC_CORE MULADDC_CORE
1520 MULADDC_CORE MULADDC_CORE
1521 MULADDC_CORE MULADDC_CORE
1522 MULADDC_CORE MULADDC_CORE
1523
1524 MULADDC_CORE MULADDC_CORE
1525 MULADDC_CORE MULADDC_CORE
1526 MULADDC_CORE MULADDC_CORE
1527 MULADDC_CORE MULADDC_CORE
1528 MULADDC_STOP
1529 }
1530
1531 for( ; i >= 8; i -= 8 )
1532 {
1533 MULADDC_INIT
1534 MULADDC_CORE MULADDC_CORE
1535 MULADDC_CORE MULADDC_CORE
1536
1537 MULADDC_CORE MULADDC_CORE
1538 MULADDC_CORE MULADDC_CORE
1539 MULADDC_STOP
1540 }
1541
1542 for( ; i > 0; i-- )
1543 {
1544 MULADDC_INIT
1545 MULADDC_CORE
1546 MULADDC_STOP
1547 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001548#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001549
1550 t++;
1551
1552 do {
1553 *d += c; c = ( *d < c ); d++;
1554 }
1555 while( c != 0 );
1556}
1557
1558/*
1559 * Baseline multiplication: X = A * B (HAC 14.12)
1560 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001561int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001562{
Paul Bakker23986e52011-04-24 08:57:21 +00001563 int ret;
1564 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001565 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001566 MPI_VALIDATE_RET( X != NULL );
1567 MPI_VALIDATE_RET( A != NULL );
1568 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001569
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001570 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001571
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001572 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1573 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001574
Paul Bakker23986e52011-04-24 08:57:21 +00001575 for( i = A->n; i > 0; i-- )
1576 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001577 break;
1578
Paul Bakker23986e52011-04-24 08:57:21 +00001579 for( j = B->n; j > 0; j-- )
1580 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001581 break;
1582
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001583 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1584 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001585
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001586 for( ; j > 0; j-- )
1587 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001588
1589 X->s = A->s * B->s;
1590
1591cleanup:
1592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001593 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001594
1595 return( ret );
1596}
1597
1598/*
1599 * Baseline multiplication: X = A * b
1600 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001601int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001602{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001603 mbedtls_mpi _B;
1604 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001605 MPI_VALIDATE_RET( X != NULL );
1606 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001607
1608 _B.s = 1;
1609 _B.n = 1;
1610 _B.p = p;
1611 p[0] = b;
1612
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001613 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001614}
1615
1616/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001617 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1618 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001619 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001620static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1621 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001622{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001623#if defined(MBEDTLS_HAVE_UDBL)
1624 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001625#else
Simon Butcher9803d072016-01-03 00:24:34 +00001626 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1627 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001628 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1629 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001630 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001631#endif
1632
Simon Butcher15b15d12015-11-26 19:35:03 +00001633 /*
1634 * Check for overflow
1635 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001636 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001637 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001638 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001639
Simon Butcherf5ba0452015-12-27 23:01:55 +00001640 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001641 }
1642
1643#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001644 dividend = (mbedtls_t_udbl) u1 << biL;
1645 dividend |= (mbedtls_t_udbl) u0;
1646 quotient = dividend / d;
1647 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1648 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1649
1650 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001651 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001652
1653 return (mbedtls_mpi_uint) quotient;
1654#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001655
1656 /*
1657 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1658 * Vol. 2 - Seminumerical Algorithms, Knuth
1659 */
1660
1661 /*
1662 * Normalize the divisor, d, and dividend, u0, u1
1663 */
1664 s = mbedtls_clz( d );
1665 d = d << s;
1666
1667 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001668 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001669 u0 = u0 << s;
1670
1671 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001672 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001673
1674 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001675 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001676
1677 /*
1678 * Find the first quotient and remainder
1679 */
1680 q1 = u1 / d1;
1681 r0 = u1 - d1 * q1;
1682
1683 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1684 {
1685 q1 -= 1;
1686 r0 += d1;
1687
1688 if ( r0 >= radix ) break;
1689 }
1690
Simon Butcherf5ba0452015-12-27 23:01:55 +00001691 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001692 q0 = rAX / d1;
1693 r0 = rAX - q0 * d1;
1694
1695 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1696 {
1697 q0 -= 1;
1698 r0 += d1;
1699
1700 if ( r0 >= radix ) break;
1701 }
1702
1703 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001704 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001705
1706 quotient = q1 * radix + q0;
1707
1708 return quotient;
1709#endif
1710}
1711
1712/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001713 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001714 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001715int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1716 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001717{
Paul Bakker23986e52011-04-24 08:57:21 +00001718 int ret;
1719 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001720 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001721 MPI_VALIDATE_RET( A != NULL );
1722 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001723
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001724 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1725 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001726
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001727 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1728 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001729
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001730 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001731 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001732 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1733 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001734 return( 0 );
1735 }
1736
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001737 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1738 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001739 X.s = Y.s = 1;
1740
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001741 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1742 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1743 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1744 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001745
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001746 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001747 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001748 {
1749 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001750 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1751 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001752 }
1753 else k = 0;
1754
1755 n = X.n - 1;
1756 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001757 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001758
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001759 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001760 {
1761 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001762 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001763 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001764 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001765
1766 for( i = n; i > t ; i-- )
1767 {
1768 if( X.p[i] >= Y.p[t] )
1769 Z.p[i - t - 1] = ~0;
1770 else
1771 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001772 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1773 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001774 }
1775
1776 Z.p[i - t - 1]++;
1777 do
1778 {
1779 Z.p[i - t - 1]--;
1780
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001781 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001782 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001783 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001784 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001785
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001786 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001787 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1788 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001789 T2.p[2] = X.p[i];
1790 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001791 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001792
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001793 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1794 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1795 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001796
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001797 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001798 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001799 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1800 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1801 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001802 Z.p[i - t - 1]--;
1803 }
1804 }
1805
1806 if( Q != NULL )
1807 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001808 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001809 Q->s = A->s * B->s;
1810 }
1811
1812 if( R != NULL )
1813 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001814 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001815 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001817
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001818 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001819 R->s = 1;
1820 }
1821
1822cleanup:
1823
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1825 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001826
1827 return( ret );
1828}
1829
1830/*
1831 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001832 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001833int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1834 const mbedtls_mpi *A,
1835 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001836{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001837 mbedtls_mpi _B;
1838 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001839 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001840
1841 p[0] = ( b < 0 ) ? -b : b;
1842 _B.s = ( b < 0 ) ? -1 : 1;
1843 _B.n = 1;
1844 _B.p = p;
1845
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001846 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001847}
1848
1849/*
1850 * Modulo: R = A mod B
1851 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001852int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001853{
1854 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001855 MPI_VALIDATE_RET( R != NULL );
1856 MPI_VALIDATE_RET( A != NULL );
1857 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001858
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001859 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1860 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001861
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001862 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001863
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001864 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1865 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001866
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001867 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1868 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001869
1870cleanup:
1871
1872 return( ret );
1873}
1874
1875/*
1876 * Modulo: r = A mod b
1877 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001878int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001879{
Paul Bakker23986e52011-04-24 08:57:21 +00001880 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001881 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001882 MPI_VALIDATE_RET( r != NULL );
1883 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001884
1885 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001886 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001887
1888 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001889 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001890
1891 /*
1892 * handle trivial cases
1893 */
1894 if( b == 1 )
1895 {
1896 *r = 0;
1897 return( 0 );
1898 }
1899
1900 if( b == 2 )
1901 {
1902 *r = A->p[0] & 1;
1903 return( 0 );
1904 }
1905
1906 /*
1907 * general case
1908 */
Paul Bakker23986e52011-04-24 08:57:21 +00001909 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001910 {
Paul Bakker23986e52011-04-24 08:57:21 +00001911 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001912 y = ( y << biH ) | ( x >> biH );
1913 z = y / b;
1914 y -= z * b;
1915
1916 x <<= biH;
1917 y = ( y << biH ) | ( x >> biH );
1918 z = y / b;
1919 y -= z * b;
1920 }
1921
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001922 /*
1923 * If A is negative, then the current y represents a negative value.
1924 * Flipping it to the positive side.
1925 */
1926 if( A->s < 0 && y != 0 )
1927 y = b - y;
1928
Paul Bakker5121ce52009-01-03 21:22:43 +00001929 *r = y;
1930
1931 return( 0 );
1932}
1933
1934/*
1935 * Fast Montgomery initialization (thanks to Tom St Denis)
1936 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001937static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001938{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001939 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001940 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001941
1942 x = m0;
1943 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001944
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001945 for( i = biL; i >= 8; i /= 2 )
1946 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001947
1948 *mm = ~x + 1;
1949}
1950
Gilles Peskine3ce3ddf2020-06-04 15:00:49 +02001951/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1952 *
1953 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine635a3742020-06-08 22:37:50 +02001954 * It must have at least as many limbs as N
1955 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine3ce3ddf2020-06-04 15:00:49 +02001956 * On successful completion, A contains the result of
1957 * the multiplication A * B * R^-1 mod N where
1958 * R = (2^ciL)^n.
1959 * \param[in] B One of the numbers to multiply.
1960 * It must be nonzero and must not have more limbs than N
1961 * (B->n <= N->n).
1962 * \param[in] N The modulo. N must be odd.
1963 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1964 * This is -N^-1 mod 2^ciL.
1965 * \param[in,out] T A bignum for temporary storage.
1966 * It must be at least twice the limb size of N plus 2
1967 * (T->n >= 2 * (N->n + 1)).
1968 * Its initial content is unused and
1969 * its final content is indeterminate.
1970 * Note that unlike the usual convention in the library
1971 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00001972 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02001973static 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 +02001974 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001975{
Paul Bakker23986e52011-04-24 08:57:21 +00001976 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001977 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001978
1979 memset( T->p, 0, T->n * ciL );
1980
1981 d = T->p;
1982 n = N->n;
1983 m = ( B->n < n ) ? B->n : n;
1984
1985 for( i = 0; i < n; i++ )
1986 {
1987 /*
1988 * T = (T + u0*B + u1*N) / 2^biL
1989 */
1990 u0 = A->p[i];
1991 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1992
1993 mpi_mul_hlp( m, B->p, d, u0 );
1994 mpi_mul_hlp( n, N->p, d, u1 );
1995
1996 *d++ = u0; d[n + 1] = 0;
1997 }
1998
Gilles Peskine635a3742020-06-08 22:37:50 +02001999 /* At this point, d is either the desired result or the desired result
2000 * plus N. We now potentially subtract N, avoiding leaking whether the
2001 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002002
Gilles Peskine635a3742020-06-08 22:37:50 +02002003 /* Copy the n least significant limbs of d to A, so that
2004 * A = d if d < N (recall that N has n limbs). */
2005 memcpy( A->p, d, n * ciL );
Gilles Peskinede719d52020-06-09 10:39:38 +02002006 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine635a3742020-06-08 22:37:50 +02002007 * do the calculation without using conditional tests. */
2008 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine8f672662020-06-04 21:05:24 +02002009 d[n] += 1;
Gilles Peskine36acd542020-06-08 21:58:22 +02002010 d[n] -= mpi_sub_hlp( n, d, N->p );
Gilles Peskine635a3742020-06-08 22:37:50 +02002011 /* If d0 < N then d < (2^biL)^n
2012 * so d[n] == 0 and we want to keep A as it is.
2013 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2014 * so d[n] == 1 and we want to set A to the result of the subtraction
2015 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2016 * This exactly corresponds to a conditional assignment. */
2017 mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002018}
2019
2020/*
2021 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine3ce3ddf2020-06-04 15:00:49 +02002022 *
2023 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00002024 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002025static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
2026 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002027{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002028 mbedtls_mpi_uint z = 1;
2029 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00002030
Paul Bakker8ddb6452013-02-27 14:56:33 +01002031 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00002032 U.p = &z;
2033
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002034 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002035}
2036
2037/*
2038 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2039 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002040int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2041 const mbedtls_mpi *E, const mbedtls_mpi *N,
2042 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00002043{
Paul Bakker23986e52011-04-24 08:57:21 +00002044 int ret;
2045 size_t wbits, wsize, one = 1;
2046 size_t i, j, nblimbs;
2047 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002048 mbedtls_mpi_uint ei, mm, state;
2049 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002050 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002051
Hanno Becker73d7d792018-12-11 10:35:51 +00002052 MPI_VALIDATE_RET( X != NULL );
2053 MPI_VALIDATE_RET( A != NULL );
2054 MPI_VALIDATE_RET( E != NULL );
2055 MPI_VALIDATE_RET( N != NULL );
2056
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01002057 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2061 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002062
2063 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002064 * Init temps and window size
2065 */
2066 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002067 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2068 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00002069 memset( W, 0, sizeof( W ) );
2070
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002071 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00002072
2073 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2074 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2075
Peter Kolbusb83d41d2018-12-11 14:01:44 -06002076#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002077 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2078 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusb83d41d2018-12-11 14:01:44 -06002079#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002080
Paul Bakker5121ce52009-01-03 21:22:43 +00002081 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002082 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2083 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2084 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002085
2086 /*
Paul Bakker50546922012-05-19 08:40:49 +00002087 * Compensate for negative A (and correct at the end)
2088 */
2089 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002090 if( neg )
2091 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002092 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002093 Apos.s = 1;
2094 A = &Apos;
2095 }
2096
2097 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002098 * If 1st call, pre-compute R^2 mod N
2099 */
2100 if( _RR == NULL || _RR->p == NULL )
2101 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002102 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2103 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2104 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002105
2106 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002107 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002108 }
2109 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002110 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002111
2112 /*
2113 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2114 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002115 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2116 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002117 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002118 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002119
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002120 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002121
2122 /*
2123 * X = R^2 * R^-1 mod N = R mod N
2124 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002125 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002126 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002127
2128 if( wsize > 1 )
2129 {
2130 /*
2131 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2132 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002133 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002134
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002135 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2136 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002137
2138 for( i = 0; i < wsize - 1; i++ )
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002139 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002140
Paul Bakker5121ce52009-01-03 21:22:43 +00002141 /*
2142 * W[i] = W[i - 1] * W[1]
2143 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002144 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002145 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002146 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2147 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002148
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002149 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002150 }
2151 }
2152
2153 nblimbs = E->n;
2154 bufsize = 0;
2155 nbits = 0;
2156 wbits = 0;
2157 state = 0;
2158
2159 while( 1 )
2160 {
2161 if( bufsize == 0 )
2162 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002163 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002164 break;
2165
Paul Bakker0d7702c2013-10-29 16:18:35 +01002166 nblimbs--;
2167
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002168 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002169 }
2170
2171 bufsize--;
2172
2173 ei = (E->p[nblimbs] >> bufsize) & 1;
2174
2175 /*
2176 * skip leading 0s
2177 */
2178 if( ei == 0 && state == 0 )
2179 continue;
2180
2181 if( ei == 0 && state == 1 )
2182 {
2183 /*
2184 * out of window, square X
2185 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002186 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002187 continue;
2188 }
2189
2190 /*
2191 * add ei to current window
2192 */
2193 state = 2;
2194
2195 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002196 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002197
2198 if( nbits == wsize )
2199 {
2200 /*
2201 * X = X^wsize R^-1 mod N
2202 */
2203 for( i = 0; i < wsize; i++ )
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002204 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002205
2206 /*
2207 * X = X * W[wbits] R^-1 mod N
2208 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002209 mpi_montmul( X, &W[wbits], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002210
2211 state--;
2212 nbits = 0;
2213 wbits = 0;
2214 }
2215 }
2216
2217 /*
2218 * process the remaining bits
2219 */
2220 for( i = 0; i < nbits; i++ )
2221 {
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002222 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002223
2224 wbits <<= 1;
2225
Paul Bakker66d5d072014-06-17 16:39:18 +02002226 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002227 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002228 }
2229
2230 /*
2231 * X = A^E * R * R^-1 mod N = A^E mod N
2232 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002233 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002234
Hanno Beckera4af1c42017-04-18 09:07:45 +01002235 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002236 {
2237 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002238 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002239 }
2240
Paul Bakker5121ce52009-01-03 21:22:43 +00002241cleanup:
2242
Paul Bakker66d5d072014-06-17 16:39:18 +02002243 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002244 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002245
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002246 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002247
Paul Bakker75a28602014-03-31 12:08:17 +02002248 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002249 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002250
2251 return( ret );
2252}
2253
Paul Bakker5121ce52009-01-03 21:22:43 +00002254/*
2255 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2256 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002257int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002258{
Paul Bakker23986e52011-04-24 08:57:21 +00002259 int ret;
2260 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002261 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002262
Hanno Becker73d7d792018-12-11 10:35:51 +00002263 MPI_VALIDATE_RET( G != NULL );
2264 MPI_VALIDATE_RET( A != NULL );
2265 MPI_VALIDATE_RET( B != NULL );
2266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002267 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002268
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002269 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2270 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002271
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 lz = mbedtls_mpi_lsb( &TA );
2273 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002274
Paul Bakker66d5d072014-06-17 16:39:18 +02002275 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002276 lz = lzt;
2277
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002278 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2279 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002280
Paul Bakker5121ce52009-01-03 21:22:43 +00002281 TA.s = TB.s = 1;
2282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002283 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002284 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002285 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2286 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002287
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002289 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002290 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2291 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002292 }
2293 else
2294 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002295 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2296 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002297 }
2298 }
2299
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002300 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2301 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002302
2303cleanup:
2304
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002305 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002306
2307 return( ret );
2308}
2309
Paul Bakker33dc46b2014-04-30 16:11:39 +02002310/*
2311 * Fill X with size bytes of random.
2312 *
2313 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002314 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002315 * deterministic, eg for tests).
2316 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002317int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002318 int (*f_rng)(void *, unsigned char *, size_t),
2319 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002320{
Paul Bakker23986e52011-04-24 08:57:21 +00002321 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002322 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002323 size_t const overhead = ( limbs * ciL ) - size;
2324 unsigned char *Xp;
2325
Hanno Becker8ce11a32018-12-19 16:18:52 +00002326 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002327 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002328
Hanno Beckerda1655a2017-10-18 14:21:44 +01002329 /* Ensure that target MPI has exactly the necessary number of limbs */
2330 if( X->n != limbs )
2331 {
2332 mbedtls_mpi_free( X );
2333 mbedtls_mpi_init( X );
2334 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2335 }
2336 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002337
Hanno Beckerda1655a2017-10-18 14:21:44 +01002338 Xp = (unsigned char*) X->p;
2339 f_rng( p_rng, Xp + overhead, size );
2340
Hanno Becker2be8a552018-10-25 12:40:09 +01002341 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002342
2343cleanup:
2344 return( ret );
2345}
2346
Paul Bakker5121ce52009-01-03 21:22:43 +00002347/*
2348 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2349 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002350int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002351{
2352 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002354 MPI_VALIDATE_RET( X != NULL );
2355 MPI_VALIDATE_RET( A != NULL );
2356 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002357
Hanno Becker4bcb4912017-04-18 15:49:39 +01002358 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002361 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2362 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2363 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002364
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002365 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002366
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002368 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002369 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002370 goto cleanup;
2371 }
2372
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002373 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2374 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2375 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2376 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002378 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2379 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2380 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2381 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002382
2383 do
2384 {
2385 while( ( TU.p[0] & 1 ) == 0 )
2386 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002387 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002388
2389 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2390 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002391 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2392 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002393 }
2394
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002395 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2396 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002397 }
2398
2399 while( ( TV.p[0] & 1 ) == 0 )
2400 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002401 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002402
2403 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2404 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002405 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2406 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002407 }
2408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002409 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2410 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002411 }
2412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002413 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002414 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002415 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2416 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2417 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002418 }
2419 else
2420 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002421 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2422 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2423 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002424 }
2425 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002426 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002427
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002428 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2429 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002431 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2432 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002435
2436cleanup:
2437
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002438 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2439 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2440 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002441
2442 return( ret );
2443}
2444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002445#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002446
Paul Bakker5121ce52009-01-03 21:22:43 +00002447static const int small_prime[] =
2448{
2449 3, 5, 7, 11, 13, 17, 19, 23,
2450 29, 31, 37, 41, 43, 47, 53, 59,
2451 61, 67, 71, 73, 79, 83, 89, 97,
2452 101, 103, 107, 109, 113, 127, 131, 137,
2453 139, 149, 151, 157, 163, 167, 173, 179,
2454 181, 191, 193, 197, 199, 211, 223, 227,
2455 229, 233, 239, 241, 251, 257, 263, 269,
2456 271, 277, 281, 283, 293, 307, 311, 313,
2457 317, 331, 337, 347, 349, 353, 359, 367,
2458 373, 379, 383, 389, 397, 401, 409, 419,
2459 421, 431, 433, 439, 443, 449, 457, 461,
2460 463, 467, 479, 487, 491, 499, 503, 509,
2461 521, 523, 541, 547, 557, 563, 569, 571,
2462 577, 587, 593, 599, 601, 607, 613, 617,
2463 619, 631, 641, 643, 647, 653, 659, 661,
2464 673, 677, 683, 691, 701, 709, 719, 727,
2465 733, 739, 743, 751, 757, 761, 769, 773,
2466 787, 797, 809, 811, 821, 823, 827, 829,
2467 839, 853, 857, 859, 863, 877, 881, 883,
2468 887, 907, 911, 919, 929, 937, 941, 947,
2469 953, 967, 971, 977, 983, 991, 997, -103
2470};
2471
2472/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002473 * Small divisors test (X must be positive)
2474 *
2475 * Return values:
2476 * 0: no small factor (possible prime, more tests needed)
2477 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002478 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002479 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002480 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002481static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002482{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002483 int ret = 0;
2484 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002485 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002486
Paul Bakker5121ce52009-01-03 21:22:43 +00002487 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002488 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002489
2490 for( i = 0; small_prime[i] > 0; i++ )
2491 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002492 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002493 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002494
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002495 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002496
2497 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002498 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002499 }
2500
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002501cleanup:
2502 return( ret );
2503}
2504
2505/*
2506 * Miller-Rabin pseudo-primality test (HAC 4.24)
2507 */
Janos Follathda31fa12018-09-03 14:45:23 +01002508static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002509 int (*f_rng)(void *, unsigned char *, size_t),
2510 void *p_rng )
2511{
Pascal Junodb99183d2015-03-11 16:49:45 +01002512 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002513 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002514 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002515
Hanno Becker8ce11a32018-12-19 16:18:52 +00002516 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002517 MPI_VALIDATE_RET( f_rng != NULL );
2518
2519 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2520 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002521 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002522
Paul Bakker5121ce52009-01-03 21:22:43 +00002523 /*
2524 * W = |X| - 1
2525 * R = W >> lsb( W )
2526 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002527 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2528 s = mbedtls_mpi_lsb( &W );
2529 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2530 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002531
Janos Follathda31fa12018-09-03 14:45:23 +01002532 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002533 {
2534 /*
2535 * pick a random A, 1 < A < |X| - 1
2536 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002537 count = 0;
2538 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002539 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002540
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002541 j = mbedtls_mpi_bitlen( &A );
2542 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002543 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002544 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002545 }
2546
2547 if (count++ > 30) {
Jens Wiklanderdfd447e2019-01-17 13:30:57 +01002548 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2549 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002550 }
2551
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002552 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2553 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002554
2555 /*
2556 * A = A^R mod |X|
2557 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002558 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002559
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002560 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2561 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002562 continue;
2563
2564 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002565 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002566 {
2567 /*
2568 * A = A * A mod |X|
2569 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002570 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2571 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002572
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002573 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002574 break;
2575
2576 j++;
2577 }
2578
2579 /*
2580 * not prime if A != |X| - 1 or A == 1
2581 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002582 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2583 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002584 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002585 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002586 break;
2587 }
2588 }
2589
2590cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002591 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2592 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002593 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002594
2595 return( ret );
2596}
2597
2598/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002599 * Pseudo-primality test: small factors, then Miller-Rabin
2600 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002601int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2602 int (*f_rng)(void *, unsigned char *, size_t),
2603 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002604{
2605 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002606 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002607 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002608 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002609
2610 XX.s = 1;
2611 XX.n = X->n;
2612 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002613
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002614 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2615 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2616 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002617
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002618 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002619 return( 0 );
2620
2621 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2622 {
2623 if( ret == 1 )
2624 return( 0 );
2625
2626 return( ret );
2627 }
2628
Janos Follathda31fa12018-09-03 14:45:23 +01002629 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002630}
2631
Janos Follatha0b67c22018-09-18 14:48:23 +01002632#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002633/*
2634 * Pseudo-primality test, error probability 2^-80
2635 */
2636int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2637 int (*f_rng)(void *, unsigned char *, size_t),
2638 void *p_rng )
2639{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002640 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002641 MPI_VALIDATE_RET( f_rng != NULL );
2642
Janos Follatha0b67c22018-09-18 14:48:23 +01002643 /*
2644 * In the past our key generation aimed for an error rate of at most
2645 * 2^-80. Since this function is deprecated, aim for the same certainty
2646 * here as well.
2647 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002648 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002649}
Janos Follatha0b67c22018-09-18 14:48:23 +01002650#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002651
2652/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002653 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002654 *
Janos Follathf301d232018-08-14 13:34:01 +01002655 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2656 * be either 1024 bits or 1536 bits long, and flags must contain
2657 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002658 */
Janos Follath7c025a92018-08-14 11:08:41 +01002659int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002660 int (*f_rng)(void *, unsigned char *, size_t),
2661 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002662{
Jethro Beekman66689272018-02-14 19:24:10 -08002663#ifdef MBEDTLS_HAVE_INT64
2664// ceil(2^63.5)
2665#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2666#else
2667// ceil(2^31.5)
2668#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2669#endif
2670 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002671 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002672 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002673 mbedtls_mpi_uint r;
2674 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002675
Hanno Becker8ce11a32018-12-19 16:18:52 +00002676 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002677 MPI_VALIDATE_RET( f_rng != NULL );
2678
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002679 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2680 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002682 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002683
2684 n = BITS_TO_LIMBS( nbits );
2685
Janos Follathda31fa12018-09-03 14:45:23 +01002686 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2687 {
2688 /*
2689 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2690 */
2691 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2692 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2693 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2694 }
2695 else
2696 {
2697 /*
2698 * 2^-100 error probability, number of rounds computed based on HAC,
2699 * fact 4.48
2700 */
2701 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2702 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2703 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2704 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2705 }
2706
Jethro Beekman66689272018-02-14 19:24:10 -08002707 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002708 {
Jethro Beekman66689272018-02-14 19:24:10 -08002709 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2710 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2711 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2712
2713 k = n * biL;
2714 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2715 X->p[0] |= 1;
2716
Janos Follath7c025a92018-08-14 11:08:41 +01002717 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002718 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002719 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002720
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002721 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002722 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002723 }
Jethro Beekman66689272018-02-14 19:24:10 -08002724 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002725 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002726 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002727 * An necessary condition for Y and X = 2Y + 1 to be prime
2728 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2729 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002730 */
Jethro Beekman66689272018-02-14 19:24:10 -08002731
2732 X->p[0] |= 2;
2733
2734 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2735 if( r == 0 )
2736 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2737 else if( r == 1 )
2738 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2739
2740 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2741 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2742 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2743
2744 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002745 {
Jethro Beekman66689272018-02-14 19:24:10 -08002746 /*
2747 * First, check small factors for X and Y
2748 * before doing Miller-Rabin on any of them
2749 */
2750 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2751 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002752 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002753 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002754 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002755 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002756 goto cleanup;
2757
2758 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2759 goto cleanup;
2760
2761 /*
2762 * Next candidates. We want to preserve Y = (X-1) / 2 and
2763 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2764 * so up Y by 6 and X by 12.
2765 */
2766 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2767 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002768 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002769 }
2770 }
2771
2772cleanup:
2773
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002774 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002775
2776 return( ret );
2777}
2778
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002779#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002780
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002781#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002782
Paul Bakker23986e52011-04-24 08:57:21 +00002783#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002784
2785static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2786{
2787 { 693, 609, 21 },
2788 { 1764, 868, 28 },
2789 { 768454923, 542167814, 1 }
2790};
2791
Paul Bakker5121ce52009-01-03 21:22:43 +00002792/*
2793 * Checkup routine
2794 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002795int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002796{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002797 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002798 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002799
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002800 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2801 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002802
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002803 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002804 "EFE021C2645FD1DC586E69184AF4A31E" \
2805 "D5F53E93B5F123FA41680867BA110131" \
2806 "944FE7952E2517337780CB0DB80E61AA" \
2807 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2808
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002809 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002810 "B2E7EFD37075B9F03FF989C7C5051C20" \
2811 "34D2A323810251127E7BF8625A4F49A5" \
2812 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2813 "5B5C25763222FEFCCFC38B832366C29E" ) );
2814
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002815 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002816 "0066A198186C18C10B2F5ED9B522752A" \
2817 "9830B69916E535C8F047518A889A43A5" \
2818 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2819
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002820 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002821
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002822 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002823 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2824 "9E857EA95A03512E2BAE7391688D264A" \
2825 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2826 "8001B72E848A38CAE1C65F78E56ABDEF" \
2827 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2828 "ECF677152EF804370C1A305CAF3B5BF1" \
2829 "30879B56C61DE584A0F53A2447A51E" ) );
2830
2831 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002832 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002833
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002834 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002835 {
2836 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002837 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002838
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002839 ret = 1;
2840 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002841 }
2842
2843 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002844 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002845
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002846 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002847
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002848 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002849 "256567336059E52CAE22925474705F39A94" ) );
2850
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002851 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002852 "6613F26162223DF488E9CD48CC132C7A" \
2853 "0AC93C701B001B092E4E5B9F73BCD27B" \
2854 "9EE50D0657C77F374E903CDFA4C642" ) );
2855
2856 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002857 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002858
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002859 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2860 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002861 {
2862 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002863 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002864
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002865 ret = 1;
2866 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002867 }
2868
2869 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002870 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002871
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002872 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002873
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002874 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002875 "36E139AEA55215609D2816998ED020BB" \
2876 "BD96C37890F65171D948E9BC7CBAA4D9" \
2877 "325D24D6A3C12710F10A09FA08AB87" ) );
2878
2879 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002880 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002881
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002882 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002883 {
2884 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002885 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002886
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002887 ret = 1;
2888 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002889 }
2890
2891 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002892 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002893
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002894 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002895
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002896 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002897 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2898 "C3DBA76456363A10869622EAC2DD84EC" \
2899 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2900
2901 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002902 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002903
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002904 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002905 {
2906 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002907 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002908
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002909 ret = 1;
2910 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002911 }
2912
2913 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002914 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002915
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002916 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002917 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002918
Paul Bakker66d5d072014-06-17 16:39:18 +02002919 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002920 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002921 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2922 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002923
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002924 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002925
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002926 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002927 {
2928 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002929 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002930
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002931 ret = 1;
2932 goto cleanup;
2933 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002934 }
2935
2936 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002937 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002938
Paul Bakker5121ce52009-01-03 21:22:43 +00002939cleanup:
2940
2941 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002942 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002943
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002944 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2945 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002946
2947 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002948 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002949
2950 return( ret );
2951}
2952
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002953#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002954
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002955#endif /* MBEDTLS_BIGNUM_C */