blob: 9b806339ed39828dece7323fa3a19f72b46ef4d0 [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úti4e9f7122020-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úti4e9f7122020-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"
Paul Bakker5121ce52009-01-03 21:22:43 +000075
Rich Evans00ab4702015-02-06 13:43:58 +000076#include <string.h>
77
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020078#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000079#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020080#else
Rich Evans00ab4702015-02-06 13:43:58 +000081#include <stdio.h>
82#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020083#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020084#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020085#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020086#endif
87
Paul Bakker34617722014-06-13 17:20:13 +020088/* Implementation that should never be optimized out by the compiler */
Alexey Skalozube17a8da2016-01-13 17:19:33 +020089static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) {
Alexey Skalozub3d53f412016-01-13 16:53:40 +020090 volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0;
Paul Bakker34617722014-06-13 17:20:13 +020091}
92
Hanno Becker88807112017-10-18 12:41:30 +010093/* Implementation that should never be optimized out by the compiler */
94static void mbedtls_zeroize( void *v, size_t n ) {
95 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
96}
97
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020098#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000099#define biL (ciL << 3) /* bits in limb */
100#define biH (ciL << 2) /* half limb size */
101
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100102#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
103
Paul Bakker5121ce52009-01-03 21:22:43 +0000104/*
105 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200106 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +0000107 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200108#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
109#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +0000110
111/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000112 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000113 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200114void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000115{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000116 if( X == NULL )
117 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000118
Paul Bakker6c591fa2011-05-05 11:49:20 +0000119 X->s = 1;
120 X->n = 0;
121 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000122}
123
124/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000125 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000126 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000128{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000129 if( X == NULL )
130 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000131
Paul Bakker6c591fa2011-05-05 11:49:20 +0000132 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200134 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000136 }
137
Paul Bakker6c591fa2011-05-05 11:49:20 +0000138 X->s = 1;
139 X->n = 0;
140 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000141}
142
143/*
144 * Enlarge to the specified number of limbs
145 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000147{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000149
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200151 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000152
Paul Bakker5121ce52009-01-03 21:22:43 +0000153 if( X->n < nblimbs )
154 {
Simon Butcher29176892016-05-20 00:19:09 +0100155 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200156 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000157
Paul Bakker5121ce52009-01-03 21:22:43 +0000158 if( X->p != NULL )
159 {
160 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200161 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000163 }
164
165 X->n = nblimbs;
166 X->p = p;
167 }
168
169 return( 0 );
170}
171
172/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100173 * Resize down as much as possible,
174 * while keeping at least the specified number of limbs
175 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100177{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200178 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100179 size_t i;
180
Gilles Peskine6a269672020-01-20 21:17:43 +0100181 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100182 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200183 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine774c1632020-01-21 13:59:51 +0100184 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100185
186 for( i = X->n - 1; i > 0; i-- )
187 if( X->p[i] != 0 )
188 break;
189 i++;
190
191 if( i < nblimbs )
192 i = nblimbs;
193
Simon Butcher29176892016-05-20 00:19:09 +0100194 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200195 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100196
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100197 if( X->p != NULL )
198 {
199 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200200 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200201 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100202 }
203
204 X->n = i;
205 X->p = p;
206
207 return( 0 );
208}
209
210/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000211 * Copy the contents of Y into X
212 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200213int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000214{
Paul Bakker23986e52011-04-24 08:57:21 +0000215 int ret;
216 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000217
218 if( X == Y )
219 return( 0 );
220
Gilles Peskine2aeab872020-01-20 21:12:50 +0100221 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200222 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200223 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200224 return( 0 );
225 }
226
Paul Bakker5121ce52009-01-03 21:22:43 +0000227 for( i = Y->n - 1; i > 0; i-- )
228 if( Y->p[i] != 0 )
229 break;
230 i++;
231
232 X->s = Y->s;
233
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200234 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000235
236 memset( X->p, 0, X->n * ciL );
237 memcpy( X->p, Y->p, i * ciL );
238
239cleanup:
240
241 return( ret );
242}
243
244/*
245 * Swap the contents of X and Y
246 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000248{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000250
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200251 memcpy( &T, X, sizeof( mbedtls_mpi ) );
252 memcpy( X, Y, sizeof( mbedtls_mpi ) );
253 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000254}
255
256/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100257 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100258 * about whether the assignment was made or not.
259 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100262{
263 int ret = 0;
264 size_t i;
265
Pascal Junodb99183d2015-03-11 16:49:45 +0100266 /* make sure assign is 0 or 1 in a time-constant manner */
267 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100268
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200269 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100270
Paul Bakker66d5d072014-06-17 16:39:18 +0200271 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100272
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100273 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200274 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100275
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100276 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200277 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100278
279cleanup:
280 return( ret );
281}
282
283/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100284 * Conditionally swap X and Y, without leaking information
285 * about whether the swap was made or not.
286 * Here it is not ok to simply swap the pointers, which whould lead to
287 * different memory access patterns when X and Y are used afterwards.
288 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200289int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100290{
291 int ret, s;
292 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100294
295 if( X == Y )
296 return( 0 );
297
Pascal Junodb99183d2015-03-11 16:49:45 +0100298 /* make sure swap is 0 or 1 in a time-constant manner */
299 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100300
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200301 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
302 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100303
304 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200305 X->s = X->s * ( 1 - swap ) + Y->s * swap;
306 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100307
308
309 for( i = 0; i < X->n; i++ )
310 {
311 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200312 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
313 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100314 }
315
316cleanup:
317 return( ret );
318}
319
320/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000321 * Set value from integer
322 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200323int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000324{
325 int ret;
326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000328 memset( X->p, 0, X->n * ciL );
329
330 X->p[0] = ( z < 0 ) ? -z : z;
331 X->s = ( z < 0 ) ? -1 : 1;
332
333cleanup:
334
335 return( ret );
336}
337
338/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000339 * Get a specific bit
340 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000342{
343 if( X->n * biL <= pos )
344 return( 0 );
345
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200346 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000347}
348
Gilles Peskine220cc172018-11-20 16:47:47 +0100349/* Get a specific byte, without range checks. */
350#define GET_BYTE( X, i ) \
351 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
352
Paul Bakker2f5947e2011-05-18 15:47:11 +0000353/*
354 * Set a bit to a specific value of 0 or 1
355 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000357{
358 int ret = 0;
359 size_t off = pos / biL;
360 size_t idx = pos % biL;
361
362 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200363 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200364
Paul Bakker2f5947e2011-05-18 15:47:11 +0000365 if( X->n * biL <= pos )
366 {
367 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200368 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200370 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000371 }
372
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200373 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
374 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000375
376cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200377
Paul Bakker2f5947e2011-05-18 15:47:11 +0000378 return( ret );
379}
380
381/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200382 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000383 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200384size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000385{
Paul Bakker23986e52011-04-24 08:57:21 +0000386 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000387
388 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000389 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000390 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
391 return( count );
392
393 return( 0 );
394}
395
396/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000397 * Count leading zero bits in a given integer
398 */
399static size_t mbedtls_clz( const mbedtls_mpi_uint x )
400{
401 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100402 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000403
404 for( j = 0; j < biL; j++ )
405 {
406 if( x & mask ) break;
407
408 mask >>= 1;
409 }
410
411 return j;
412}
413
414/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200415 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000416 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200417size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000418{
Paul Bakker23986e52011-04-24 08:57:21 +0000419 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000420
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200421 if( X->n == 0 )
422 return( 0 );
423
Paul Bakker5121ce52009-01-03 21:22:43 +0000424 for( i = X->n - 1; i > 0; i-- )
425 if( X->p[i] != 0 )
426 break;
427
Simon Butcher15b15d12015-11-26 19:35:03 +0000428 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000429
Paul Bakker23986e52011-04-24 08:57:21 +0000430 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000431}
432
433/*
434 * Return the total size in bytes
435 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200436size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000437{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200438 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000439}
440
441/*
442 * Convert an ASCII character to digit value
443 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200444static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000445{
446 *d = 255;
447
448 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
449 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
450 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
451
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452 if( *d >= (mbedtls_mpi_uint) radix )
453 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000454
455 return( 0 );
456}
457
458/*
459 * Import from an ASCII string
460 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200461int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000462{
Paul Bakker23986e52011-04-24 08:57:21 +0000463 int ret;
464 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 mbedtls_mpi_uint d;
466 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000467
468 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200469 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000472
Paul Bakkerff60ee62010-03-16 21:09:09 +0000473 slen = strlen( s );
474
Paul Bakker5121ce52009-01-03 21:22:43 +0000475 if( radix == 16 )
476 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100477 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200478 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
479
Paul Bakkerff60ee62010-03-16 21:09:09 +0000480 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
483 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000484
Paul Bakker23986e52011-04-24 08:57:21 +0000485 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000486 {
Paul Bakker23986e52011-04-24 08:57:21 +0000487 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000488 {
489 X->s = -1;
490 break;
491 }
492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200494 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000495 }
496 }
497 else
498 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000500
Paul Bakkerff60ee62010-03-16 21:09:09 +0000501 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000502 {
503 if( i == 0 && s[i] == '-' )
504 {
505 X->s = -1;
506 continue;
507 }
508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
510 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000511
512 if( X->s == 1 )
513 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000515 }
516 else
517 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000519 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000520 }
521 }
522
523cleanup:
524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000526
527 return( ret );
528}
529
530/*
Ron Eldore6cbfc32018-11-20 14:07:01 +0200531 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000532 */
Ron Eldore6cbfc32018-11-20 14:07:01 +0200533static int mpi_write_hlp( mbedtls_mpi *X, int radix,
534 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000535{
536 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537 mbedtls_mpi_uint r;
Ron Eldore6cbfc32018-11-20 14:07:01 +0200538 size_t length = 0;
539 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000540
Ron Eldore6cbfc32018-11-20 14:07:01 +0200541 do
542 {
543 if( length >= buflen )
544 {
545 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
546 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000547
Ron Eldore6cbfc32018-11-20 14:07:01 +0200548 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
549 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
550 /*
551 * Write the residue in the current position, as an ASCII character.
552 */
553 if( r < 0xA )
554 *(--p_end) = (char)( '0' + r );
555 else
556 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000557
Ron Eldore6cbfc32018-11-20 14:07:01 +0200558 length++;
559 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000560
Ron Eldore6cbfc32018-11-20 14:07:01 +0200561 memmove( *p, p_end, length );
562 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000563
564cleanup:
565
566 return( ret );
567}
568
569/*
570 * Export into an ASCII string
571 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100572int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
573 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000574{
Paul Bakker23986e52011-04-24 08:57:21 +0000575 int ret = 0;
576 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000577 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000579
580 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200581 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000582
Hanno Beckera277d4c2019-02-04 09:45:07 +0000583 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
584 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
585 * `n`. If radix > 4, this might be a strict
586 * overapproximation of the number of
587 * radix-adic digits needed to present `n`. */
588 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
589 * present `n`. */
590
Janos Follath216e7382019-03-06 13:43:02 +0000591 n += 1; /* Terminating null byte */
Hanno Beckera277d4c2019-02-04 09:45:07 +0000592 n += 1; /* Compensate for the divisions above, which round down `n`
593 * in case it's not even. */
594 n += 1; /* Potential '-'-sign. */
595 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
596 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000597
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100598 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000599 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100600 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200601 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000602 }
603
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100604 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200605 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000606
607 if( X->s == -1 )
Hanno Beckereff335d2019-02-01 16:41:30 +0000608 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000609 *p++ = '-';
Hanno Beckereff335d2019-02-01 16:41:30 +0000610 buflen--;
611 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000612
613 if( radix == 16 )
614 {
Paul Bakker23986e52011-04-24 08:57:21 +0000615 int c;
616 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000617
Paul Bakker23986e52011-04-24 08:57:21 +0000618 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000619 {
Paul Bakker23986e52011-04-24 08:57:21 +0000620 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000621 {
Paul Bakker23986e52011-04-24 08:57:21 +0000622 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000623
Paul Bakker6c343d72014-07-10 14:36:19 +0200624 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000625 continue;
626
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000627 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000628 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000629 k = 1;
630 }
631 }
632 }
633 else
634 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000636
637 if( T.s == -1 )
638 T.s = 1;
639
Ron Eldore6cbfc32018-11-20 14:07:01 +0200640 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000641 }
642
643 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100644 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000645
646cleanup:
647
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000649
650 return( ret );
651}
652
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000654/*
655 * Read X from an opened file
656 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200657int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000658{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000660 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000661 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000662 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000663 * Buffer should have space for (short) label and decimal formatted MPI,
664 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000665 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000667
668 memset( s, 0, sizeof( s ) );
669 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000671
672 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000673 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000675
Hanno Beckerb2034b72017-04-26 11:46:46 +0100676 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
677 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000678
679 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100680 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000681 if( mpi_get_digit( &d, radix, *p ) != 0 )
682 break;
683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000685}
686
687/*
688 * Write X into an opened file (or stdout if fout == NULL)
689 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000691{
Paul Bakker23986e52011-04-24 08:57:21 +0000692 int ret;
693 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000694 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000695 * Buffer should have space for (short) label and decimal formatted MPI,
696 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000697 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000699
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100700 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000701
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100702 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000703
704 if( p == NULL ) p = "";
705
706 plen = strlen( p );
707 slen = strlen( s );
708 s[slen++] = '\r';
709 s[slen++] = '\n';
710
711 if( fout != NULL )
712 {
713 if( fwrite( p, 1, plen, fout ) != plen ||
714 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200715 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000716 }
717 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200718 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000719
720cleanup:
721
722 return( ret );
723}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200724#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000725
726/*
727 * Import X from unsigned binary data, big endian
728 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200729int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000730{
Paul Bakker23986e52011-04-24 08:57:21 +0000731 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100732 size_t i, j;
733 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000734
Hanno Becker073c1992017-10-17 15:17:27 +0100735 /* Ensure that target MPI has exactly the necessary number of limbs */
736 if( X->n != limbs )
737 {
738 mbedtls_mpi_free( X );
739 mbedtls_mpi_init( X );
740 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
741 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000742
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000744
Hanno Becker073c1992017-10-17 15:17:27 +0100745 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200746 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000747
748cleanup:
749
750 return( ret );
751}
752
753/*
754 * Export X into unsigned binary data, big endian
755 */
Gilles Peskine220cc172018-11-20 16:47:47 +0100756int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
757 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000758{
Gilles Peskine220cc172018-11-20 16:47:47 +0100759 size_t stored_bytes = X->n * ciL;
760 size_t bytes_to_copy;
761 unsigned char *p;
762 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000763
Gilles Peskine220cc172018-11-20 16:47:47 +0100764 if( stored_bytes < buflen )
765 {
766 /* There is enough space in the output buffer. Write initial
767 * null bytes and record the position at which to start
768 * writing the significant bytes. In this case, the execution
769 * trace of this function does not depend on the value of the
770 * number. */
771 bytes_to_copy = stored_bytes;
772 p = buf + buflen - stored_bytes;
773 memset( buf, 0, buflen - stored_bytes );
774 }
775 else
776 {
777 /* The output buffer is smaller than the allocated size of X.
778 * However X may fit if its leading bytes are zero. */
779 bytes_to_copy = buflen;
780 p = buf;
781 for( i = bytes_to_copy; i < stored_bytes; i++ )
782 {
783 if( GET_BYTE( X, i ) != 0 )
784 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
785 }
786 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000787
Gilles Peskine220cc172018-11-20 16:47:47 +0100788 for( i = 0; i < bytes_to_copy; i++ )
789 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000790
791 return( 0 );
792}
793
794/*
795 * Left-shift: X <<= count
796 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200797int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000798{
Paul Bakker23986e52011-04-24 08:57:21 +0000799 int ret;
800 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200801 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000802
803 v0 = count / (biL );
804 t1 = count & (biL - 1);
805
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200806 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000807
Paul Bakkerf9688572011-05-05 10:00:45 +0000808 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200809 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000810
811 ret = 0;
812
813 /*
814 * shift by count / limb_size
815 */
816 if( v0 > 0 )
817 {
Paul Bakker23986e52011-04-24 08:57:21 +0000818 for( i = X->n; i > v0; i-- )
819 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000820
Paul Bakker23986e52011-04-24 08:57:21 +0000821 for( ; i > 0; i-- )
822 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000823 }
824
825 /*
826 * shift by count % limb_size
827 */
828 if( t1 > 0 )
829 {
830 for( i = v0; i < X->n; i++ )
831 {
832 r1 = X->p[i] >> (biL - t1);
833 X->p[i] <<= t1;
834 X->p[i] |= r0;
835 r0 = r1;
836 }
837 }
838
839cleanup:
840
841 return( ret );
842}
843
844/*
845 * Right-shift: X >>= count
846 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200847int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000848{
Paul Bakker23986e52011-04-24 08:57:21 +0000849 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200850 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000851
852 v0 = count / biL;
853 v1 = count & (biL - 1);
854
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100855 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200856 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100857
Paul Bakker5121ce52009-01-03 21:22:43 +0000858 /*
859 * shift by count / limb_size
860 */
861 if( v0 > 0 )
862 {
863 for( i = 0; i < X->n - v0; i++ )
864 X->p[i] = X->p[i + v0];
865
866 for( ; i < X->n; i++ )
867 X->p[i] = 0;
868 }
869
870 /*
871 * shift by count % limb_size
872 */
873 if( v1 > 0 )
874 {
Paul Bakker23986e52011-04-24 08:57:21 +0000875 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000876 {
Paul Bakker23986e52011-04-24 08:57:21 +0000877 r1 = X->p[i - 1] << (biL - v1);
878 X->p[i - 1] >>= v1;
879 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000880 r0 = r1;
881 }
882 }
883
884 return( 0 );
885}
886
887/*
888 * Compare unsigned values
889 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200890int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000891{
Paul Bakker23986e52011-04-24 08:57:21 +0000892 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000893
Paul Bakker23986e52011-04-24 08:57:21 +0000894 for( i = X->n; i > 0; i-- )
895 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000896 break;
897
Paul Bakker23986e52011-04-24 08:57:21 +0000898 for( j = Y->n; j > 0; j-- )
899 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000900 break;
901
Paul Bakker23986e52011-04-24 08:57:21 +0000902 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000903 return( 0 );
904
905 if( i > j ) return( 1 );
906 if( j > i ) return( -1 );
907
Paul Bakker23986e52011-04-24 08:57:21 +0000908 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000909 {
Paul Bakker23986e52011-04-24 08:57:21 +0000910 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
911 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000912 }
913
914 return( 0 );
915}
916
917/*
918 * Compare signed values
919 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200920int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000921{
Paul Bakker23986e52011-04-24 08:57:21 +0000922 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000923
Paul Bakker23986e52011-04-24 08:57:21 +0000924 for( i = X->n; i > 0; i-- )
925 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000926 break;
927
Paul Bakker23986e52011-04-24 08:57:21 +0000928 for( j = Y->n; j > 0; j-- )
929 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000930 break;
931
Paul Bakker23986e52011-04-24 08:57:21 +0000932 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000933 return( 0 );
934
935 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000936 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000937
938 if( X->s > 0 && Y->s < 0 ) return( 1 );
939 if( Y->s > 0 && X->s < 0 ) return( -1 );
940
Paul Bakker23986e52011-04-24 08:57:21 +0000941 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000942 {
Paul Bakker23986e52011-04-24 08:57:21 +0000943 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
944 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000945 }
946
947 return( 0 );
948}
949
Janos Follath3173a532019-10-14 09:09:32 +0100950/** Decide if an integer is less than the other, without branches.
951 *
952 * \param x First integer.
953 * \param y Second integer.
954 *
955 * \return 1 if \p x is less than \p y, 0 otherwise
956 */
Janos Follathc3b376e2019-10-11 14:21:53 +0100957static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
958 const mbedtls_mpi_uint y )
Janos Follathe0187b92019-09-05 14:47:19 +0100959{
960 mbedtls_mpi_uint ret;
961 mbedtls_mpi_uint cond;
962
963 /*
964 * Check if the most significant bits (MSB) of the operands are different.
965 */
966 cond = ( x ^ y );
967 /*
968 * If the MSB are the same then the difference x-y will be negative (and
969 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
970 */
971 ret = ( x - y ) & ~cond;
972 /*
973 * If the MSB are different, then the operand with the MSB of 1 is the
974 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
975 * the MSB of y is 0.)
976 */
977 ret |= y & cond;
978
979
Janos Follathdb9f4492019-10-14 08:59:14 +0100980 ret = ret >> ( biL - 1 );
Janos Follathe0187b92019-09-05 14:47:19 +0100981
Janos Follath58239612019-10-29 15:08:46 +0000982 return (unsigned) ret;
Janos Follathe0187b92019-09-05 14:47:19 +0100983}
984
985/*
986 * Compare signed values in constant time
987 */
Janos Follathc3b376e2019-10-11 14:21:53 +0100988int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
989 unsigned *ret )
Janos Follathe0187b92019-09-05 14:47:19 +0100990{
991 size_t i;
Janos Follatha2b9a962019-10-28 12:23:18 +0000992 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath8ec2a952019-10-28 12:31:34 +0000993 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathe0187b92019-09-05 14:47:19 +0100994
995 if( X->n != Y->n )
996 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
997
998 /*
Janos Follath51ed14e2019-10-28 12:12:15 +0000999 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1000 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathe0187b92019-09-05 14:47:19 +01001001 */
Janos Follath8ec2a952019-10-28 12:31:34 +00001002 X_is_negative = ( X->s & 2 ) >> 1;
1003 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follathc3b376e2019-10-11 14:21:53 +01001004
1005 /*
1006 * If the signs are different, then the positive operand is the bigger.
Janos Follath8ec2a952019-10-28 12:31:34 +00001007 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1008 * is false if X is positive (X_is_negative == 0).
Janos Follathc3b376e2019-10-11 14:21:53 +01001009 */
Janos Follath8ec2a952019-10-28 12:31:34 +00001010 cond = ( X_is_negative ^ Y_is_negative );
1011 *ret = cond & X_is_negative;
Janos Follathc3b376e2019-10-11 14:21:53 +01001012
1013 /*
Janos Follatha2b9a962019-10-28 12:23:18 +00001014 * This is a constant-time function. We might have the result, but we still
Janos Follathc3b376e2019-10-11 14:21:53 +01001015 * need to go through the loop. Record if we have the result already.
1016 */
Janos Follathe0187b92019-09-05 14:47:19 +01001017 done = cond;
1018
1019 for( i = X->n; i > 0; i-- )
1020 {
1021 /*
Janos Follathb4edac52019-11-05 12:24:52 +00001022 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1023 * X and Y are negative.
Janos Follathc3b376e2019-10-11 14:21:53 +01001024 *
1025 * Again even if we can make a decision, we just mark the result and
1026 * the fact that we are done and continue looping.
Janos Follathe0187b92019-09-05 14:47:19 +01001027 */
Janos Follathb4edac52019-11-05 12:24:52 +00001028 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1029 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathcff9e6e2019-10-28 12:37:21 +00001030 done |= cond;
Janos Follathe0187b92019-09-05 14:47:19 +01001031
1032 /*
Janos Follathb4edac52019-11-05 12:24:52 +00001033 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1034 * X and Y are positive.
Janos Follathc3b376e2019-10-11 14:21:53 +01001035 *
1036 * Again even if we can make a decision, we just mark the result and
1037 * the fact that we are done and continue looping.
Janos Follathe0187b92019-09-05 14:47:19 +01001038 */
Janos Follathb4edac52019-11-05 12:24:52 +00001039 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1040 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathcff9e6e2019-10-28 12:37:21 +00001041 done |= cond;
Janos Follathe0187b92019-09-05 14:47:19 +01001042 }
1043
1044 return( 0 );
1045}
1046
Paul Bakker5121ce52009-01-03 21:22:43 +00001047/*
1048 * Compare signed values
1049 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001051{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001052 mbedtls_mpi Y;
1053 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001054
1055 *p = ( z < 0 ) ? -z : z;
1056 Y.s = ( z < 0 ) ? -1 : 1;
1057 Y.n = 1;
1058 Y.p = p;
1059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001060 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001061}
1062
1063/*
1064 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1065 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001066int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001067{
Paul Bakker23986e52011-04-24 08:57:21 +00001068 int ret;
1069 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001070 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +00001071
1072 if( X == B )
1073 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001074 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001075 }
1076
1077 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001078 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001079
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001080 /*
1081 * X should always be positive as a result of unsigned additions.
1082 */
1083 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001084
Paul Bakker23986e52011-04-24 08:57:21 +00001085 for( j = B->n; j > 0; j-- )
1086 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001087 break;
1088
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001089 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001090
1091 o = B->p; p = X->p; c = 0;
1092
Janos Follath6c922682015-10-30 17:43:11 +01001093 /*
1094 * tmp is used because it might happen that p == o
1095 */
Paul Bakker23986e52011-04-24 08:57:21 +00001096 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001097 {
Janos Follath6c922682015-10-30 17:43:11 +01001098 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001099 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001100 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001101 }
1102
1103 while( c != 0 )
1104 {
1105 if( i >= X->n )
1106 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001107 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001108 p = X->p + i;
1109 }
1110
Paul Bakker2d319fd2012-09-16 21:34:26 +00001111 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001112 }
1113
1114cleanup:
1115
1116 return( ret );
1117}
1118
1119/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001120 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001121 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001122static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001123{
Paul Bakker23986e52011-04-24 08:57:21 +00001124 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001125 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001126
1127 for( i = c = 0; i < n; i++, s++, d++ )
1128 {
1129 z = ( *d < c ); *d -= c;
1130 c = ( *d < *s ) + z; *d -= *s;
1131 }
1132
1133 while( c != 0 )
1134 {
1135 z = ( *d < c ); *d -= c;
1136 c = z; i++; d++;
1137 }
1138}
1139
1140/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001141 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001142 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001143int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001144{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001145 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001146 int ret;
1147 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001148
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001149 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1150 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001152 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001153
1154 if( X == B )
1155 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001156 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001157 B = &TB;
1158 }
1159
1160 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001161 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001162
Paul Bakker1ef7a532009-06-20 10:50:55 +00001163 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001164 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001165 */
1166 X->s = 1;
1167
Paul Bakker5121ce52009-01-03 21:22:43 +00001168 ret = 0;
1169
Paul Bakker23986e52011-04-24 08:57:21 +00001170 for( n = B->n; n > 0; n-- )
1171 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001172 break;
1173
Paul Bakker23986e52011-04-24 08:57:21 +00001174 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001175
1176cleanup:
1177
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001178 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001179
1180 return( ret );
1181}
1182
1183/*
1184 * Signed addition: X = A + B
1185 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001186int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001187{
1188 int ret, s = A->s;
1189
1190 if( A->s * B->s < 0 )
1191 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001192 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001193 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001194 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001195 X->s = s;
1196 }
1197 else
1198 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001199 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001200 X->s = -s;
1201 }
1202 }
1203 else
1204 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001205 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001206 X->s = s;
1207 }
1208
1209cleanup:
1210
1211 return( ret );
1212}
1213
1214/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001215 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001216 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001217int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001218{
1219 int ret, s = A->s;
1220
1221 if( A->s * B->s > 0 )
1222 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001223 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001224 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001225 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001226 X->s = s;
1227 }
1228 else
1229 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001230 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001231 X->s = -s;
1232 }
1233 }
1234 else
1235 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001236 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001237 X->s = s;
1238 }
1239
1240cleanup:
1241
1242 return( ret );
1243}
1244
1245/*
1246 * Signed addition: X = A + b
1247 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001248int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001249{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001250 mbedtls_mpi _B;
1251 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001252
1253 p[0] = ( b < 0 ) ? -b : b;
1254 _B.s = ( b < 0 ) ? -1 : 1;
1255 _B.n = 1;
1256 _B.p = p;
1257
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001258 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001259}
1260
1261/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001262 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001263 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001264int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001265{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001266 mbedtls_mpi _B;
1267 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001268
1269 p[0] = ( b < 0 ) ? -b : b;
1270 _B.s = ( b < 0 ) ? -1 : 1;
1271 _B.n = 1;
1272 _B.p = p;
1273
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001274 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001275}
1276
1277/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001278 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001279 */
1280static
1281#if defined(__APPLE__) && defined(__arm__)
1282/*
1283 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1284 * appears to need this to prevent bad ARM code generation at -O3.
1285 */
1286__attribute__ ((noinline))
1287#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001288void 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 +00001289{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001290 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001291
1292#if defined(MULADDC_HUIT)
1293 for( ; i >= 8; i -= 8 )
1294 {
1295 MULADDC_INIT
1296 MULADDC_HUIT
1297 MULADDC_STOP
1298 }
1299
1300 for( ; i > 0; i-- )
1301 {
1302 MULADDC_INIT
1303 MULADDC_CORE
1304 MULADDC_STOP
1305 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001306#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001307 for( ; i >= 16; i -= 16 )
1308 {
1309 MULADDC_INIT
1310 MULADDC_CORE MULADDC_CORE
1311 MULADDC_CORE MULADDC_CORE
1312 MULADDC_CORE MULADDC_CORE
1313 MULADDC_CORE MULADDC_CORE
1314
1315 MULADDC_CORE MULADDC_CORE
1316 MULADDC_CORE MULADDC_CORE
1317 MULADDC_CORE MULADDC_CORE
1318 MULADDC_CORE MULADDC_CORE
1319 MULADDC_STOP
1320 }
1321
1322 for( ; i >= 8; i -= 8 )
1323 {
1324 MULADDC_INIT
1325 MULADDC_CORE MULADDC_CORE
1326 MULADDC_CORE MULADDC_CORE
1327
1328 MULADDC_CORE MULADDC_CORE
1329 MULADDC_CORE MULADDC_CORE
1330 MULADDC_STOP
1331 }
1332
1333 for( ; i > 0; i-- )
1334 {
1335 MULADDC_INIT
1336 MULADDC_CORE
1337 MULADDC_STOP
1338 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001339#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001340
1341 t++;
1342
1343 do {
1344 *d += c; c = ( *d < c ); d++;
1345 }
1346 while( c != 0 );
1347}
1348
1349/*
1350 * Baseline multiplication: X = A * B (HAC 14.12)
1351 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001352int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001353{
Paul Bakker23986e52011-04-24 08:57:21 +00001354 int ret;
1355 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001356 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001358 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001359
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001360 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1361 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001362
Paul Bakker23986e52011-04-24 08:57:21 +00001363 for( i = A->n; i > 0; i-- )
1364 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001365 break;
1366
Paul Bakker23986e52011-04-24 08:57:21 +00001367 for( j = B->n; j > 0; j-- )
1368 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001369 break;
1370
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001371 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1372 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001373
Paul Bakker23986e52011-04-24 08:57:21 +00001374 for( i++; j > 0; j-- )
1375 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001376
1377 X->s = A->s * B->s;
1378
1379cleanup:
1380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001381 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001382
1383 return( ret );
1384}
1385
1386/*
1387 * Baseline multiplication: X = A * b
1388 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001389int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001390{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391 mbedtls_mpi _B;
1392 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001393
1394 _B.s = 1;
1395 _B.n = 1;
1396 _B.p = p;
1397 p[0] = b;
1398
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001400}
1401
1402/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001403 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1404 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001405 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001406static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1407 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001408{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001409#if defined(MBEDTLS_HAVE_UDBL)
1410 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001411#else
Simon Butcher9803d072016-01-03 00:24:34 +00001412 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1413 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001414 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1415 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001416 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001417#endif
1418
Simon Butcher15b15d12015-11-26 19:35:03 +00001419 /*
1420 * Check for overflow
1421 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001422 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001423 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001424 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001425
Simon Butcherf5ba0452015-12-27 23:01:55 +00001426 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001427 }
1428
1429#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001430 dividend = (mbedtls_t_udbl) u1 << biL;
1431 dividend |= (mbedtls_t_udbl) u0;
1432 quotient = dividend / d;
1433 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1434 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1435
1436 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001437 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001438
1439 return (mbedtls_mpi_uint) quotient;
1440#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001441
1442 /*
1443 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1444 * Vol. 2 - Seminumerical Algorithms, Knuth
1445 */
1446
1447 /*
1448 * Normalize the divisor, d, and dividend, u0, u1
1449 */
1450 s = mbedtls_clz( d );
1451 d = d << s;
1452
1453 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001454 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001455 u0 = u0 << s;
1456
1457 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001458 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001459
1460 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001461 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001462
1463 /*
1464 * Find the first quotient and remainder
1465 */
1466 q1 = u1 / d1;
1467 r0 = u1 - d1 * q1;
1468
1469 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1470 {
1471 q1 -= 1;
1472 r0 += d1;
1473
1474 if ( r0 >= radix ) break;
1475 }
1476
Simon Butcherf5ba0452015-12-27 23:01:55 +00001477 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001478 q0 = rAX / d1;
1479 r0 = rAX - q0 * d1;
1480
1481 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1482 {
1483 q0 -= 1;
1484 r0 += d1;
1485
1486 if ( r0 >= radix ) break;
1487 }
1488
1489 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001490 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001491
1492 quotient = q1 * radix + q0;
1493
1494 return quotient;
1495#endif
1496}
1497
1498/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001499 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001500 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001501int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001502{
Paul Bakker23986e52011-04-24 08:57:21 +00001503 int ret;
1504 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001505 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001507 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1508 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001509
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001510 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1511 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001513 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001514 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001515 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1516 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001517 return( 0 );
1518 }
1519
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001520 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1521 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001522 X.s = Y.s = 1;
1523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001524 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1525 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1526 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1527 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001528
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001529 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001530 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001531 {
1532 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001533 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1534 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001535 }
1536 else k = 0;
1537
1538 n = X.n - 1;
1539 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001540 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001541
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001542 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001543 {
1544 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001545 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001546 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001547 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001548
1549 for( i = n; i > t ; i-- )
1550 {
1551 if( X.p[i] >= Y.p[t] )
1552 Z.p[i - t - 1] = ~0;
1553 else
1554 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001555 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1556 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001557 }
1558
1559 Z.p[i - t - 1]++;
1560 do
1561 {
1562 Z.p[i - t - 1]--;
1563
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001564 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001565 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001566 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001567 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001568
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001569 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001570 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1571 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001572 T2.p[2] = X.p[i];
1573 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001574 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001576 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1577 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1578 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001579
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001580 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001581 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001582 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1583 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1584 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001585 Z.p[i - t - 1]--;
1586 }
1587 }
1588
1589 if( Q != NULL )
1590 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001591 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001592 Q->s = A->s * B->s;
1593 }
1594
1595 if( R != NULL )
1596 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001597 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001598 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001599 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001600
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001601 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001602 R->s = 1;
1603 }
1604
1605cleanup:
1606
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001607 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1608 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001609
1610 return( ret );
1611}
1612
1613/*
1614 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001615 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001616int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001617{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001618 mbedtls_mpi _B;
1619 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001620
1621 p[0] = ( b < 0 ) ? -b : b;
1622 _B.s = ( b < 0 ) ? -1 : 1;
1623 _B.n = 1;
1624 _B.p = p;
1625
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001626 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001627}
1628
1629/*
1630 * Modulo: R = A mod B
1631 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001632int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001633{
1634 int ret;
1635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1637 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001638
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001639 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001640
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001641 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1642 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001643
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001644 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1645 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001646
1647cleanup:
1648
1649 return( ret );
1650}
1651
1652/*
1653 * Modulo: r = A mod b
1654 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001655int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001656{
Paul Bakker23986e52011-04-24 08:57:21 +00001657 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001658 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001659
1660 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001662
1663 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001664 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001665
1666 /*
1667 * handle trivial cases
1668 */
1669 if( b == 1 )
1670 {
1671 *r = 0;
1672 return( 0 );
1673 }
1674
1675 if( b == 2 )
1676 {
1677 *r = A->p[0] & 1;
1678 return( 0 );
1679 }
1680
1681 /*
1682 * general case
1683 */
Paul Bakker23986e52011-04-24 08:57:21 +00001684 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001685 {
Paul Bakker23986e52011-04-24 08:57:21 +00001686 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001687 y = ( y << biH ) | ( x >> biH );
1688 z = y / b;
1689 y -= z * b;
1690
1691 x <<= biH;
1692 y = ( y << biH ) | ( x >> biH );
1693 z = y / b;
1694 y -= z * b;
1695 }
1696
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001697 /*
1698 * If A is negative, then the current y represents a negative value.
1699 * Flipping it to the positive side.
1700 */
1701 if( A->s < 0 && y != 0 )
1702 y = b - y;
1703
Paul Bakker5121ce52009-01-03 21:22:43 +00001704 *r = y;
1705
1706 return( 0 );
1707}
1708
1709/*
1710 * Fast Montgomery initialization (thanks to Tom St Denis)
1711 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001712static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001713{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001714 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001715 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001716
1717 x = m0;
1718 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001719
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001720 for( i = biL; i >= 8; i /= 2 )
1721 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001722
1723 *mm = ~x + 1;
1724}
1725
1726/*
1727 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1728 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001729static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001730 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001731{
Paul Bakker23986e52011-04-24 08:57:21 +00001732 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001733 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001734
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001735 if( T->n < N->n + 1 || T->p == NULL )
1736 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1737
Paul Bakker5121ce52009-01-03 21:22:43 +00001738 memset( T->p, 0, T->n * ciL );
1739
1740 d = T->p;
1741 n = N->n;
1742 m = ( B->n < n ) ? B->n : n;
1743
1744 for( i = 0; i < n; i++ )
1745 {
1746 /*
1747 * T = (T + u0*B + u1*N) / 2^biL
1748 */
1749 u0 = A->p[i];
1750 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1751
1752 mpi_mul_hlp( m, B->p, d, u0 );
1753 mpi_mul_hlp( n, N->p, d, u1 );
1754
1755 *d++ = u0; d[n + 1] = 0;
1756 }
1757
Paul Bakker66d5d072014-06-17 16:39:18 +02001758 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001759
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001760 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001761 mpi_sub_hlp( n, N->p, A->p );
1762 else
1763 /* prevent timing attacks */
1764 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001765
1766 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001767}
1768
1769/*
1770 * Montgomery reduction: A = A * R^-1 mod N
1771 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001772static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001773{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001774 mbedtls_mpi_uint z = 1;
1775 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001776
Paul Bakker8ddb6452013-02-27 14:56:33 +01001777 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001778 U.p = &z;
1779
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001780 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001781}
1782
1783/*
1784 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1785 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001786int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001787{
Paul Bakker23986e52011-04-24 08:57:21 +00001788 int ret;
1789 size_t wbits, wsize, one = 1;
1790 size_t i, j, nblimbs;
1791 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001792 mbedtls_mpi_uint ei, mm, state;
1793 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001794 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001795
Hanno Becker930ec7d2018-03-09 10:48:00 +00001796 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001797 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001798
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001799 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1800 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001801
1802 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001803 * Init temps and window size
1804 */
1805 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001806 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1807 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001808 memset( W, 0, sizeof( W ) );
1809
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001810 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001811
1812 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1813 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1814
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001815#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1817 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001818#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001819
Paul Bakker5121ce52009-01-03 21:22:43 +00001820 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001821 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1822 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1823 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001824
1825 /*
Paul Bakker50546922012-05-19 08:40:49 +00001826 * Compensate for negative A (and correct at the end)
1827 */
1828 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001829 if( neg )
1830 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001831 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001832 Apos.s = 1;
1833 A = &Apos;
1834 }
1835
1836 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001837 * If 1st call, pre-compute R^2 mod N
1838 */
1839 if( _RR == NULL || _RR->p == NULL )
1840 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001841 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1842 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1843 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001844
1845 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001846 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001847 }
1848 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001849 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001850
1851 /*
1852 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1853 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001854 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1855 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001856 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001857 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001858
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001859 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001860
1861 /*
1862 * X = R^2 * R^-1 mod N = R mod N
1863 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001864 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001865 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001866
1867 if( wsize > 1 )
1868 {
1869 /*
1870 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1871 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001872 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001873
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001874 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1875 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001876
1877 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001878 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001879
Paul Bakker5121ce52009-01-03 21:22:43 +00001880 /*
1881 * W[i] = W[i - 1] * W[1]
1882 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001883 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001884 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001885 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1886 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001887
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001888 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001889 }
1890 }
1891
1892 nblimbs = E->n;
1893 bufsize = 0;
1894 nbits = 0;
1895 wbits = 0;
1896 state = 0;
1897
1898 while( 1 )
1899 {
1900 if( bufsize == 0 )
1901 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001902 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001903 break;
1904
Paul Bakker0d7702c2013-10-29 16:18:35 +01001905 nblimbs--;
1906
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001907 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001908 }
1909
1910 bufsize--;
1911
1912 ei = (E->p[nblimbs] >> bufsize) & 1;
1913
1914 /*
1915 * skip leading 0s
1916 */
1917 if( ei == 0 && state == 0 )
1918 continue;
1919
1920 if( ei == 0 && state == 1 )
1921 {
1922 /*
1923 * out of window, square X
1924 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001925 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001926 continue;
1927 }
1928
1929 /*
1930 * add ei to current window
1931 */
1932 state = 2;
1933
1934 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001935 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001936
1937 if( nbits == wsize )
1938 {
1939 /*
1940 * X = X^wsize R^-1 mod N
1941 */
1942 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001943 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001944
1945 /*
1946 * X = X * W[wbits] R^-1 mod N
1947 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001948 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001949
1950 state--;
1951 nbits = 0;
1952 wbits = 0;
1953 }
1954 }
1955
1956 /*
1957 * process the remaining bits
1958 */
1959 for( i = 0; i < nbits; i++ )
1960 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001961 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001962
1963 wbits <<= 1;
1964
Paul Bakker66d5d072014-06-17 16:39:18 +02001965 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001966 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001967 }
1968
1969 /*
1970 * X = A^E * R * R^-1 mod N = A^E mod N
1971 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001972 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001973
Hanno Beckera4af1c42017-04-18 09:07:45 +01001974 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001975 {
1976 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001977 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001978 }
1979
Paul Bakker5121ce52009-01-03 21:22:43 +00001980cleanup:
1981
Paul Bakker66d5d072014-06-17 16:39:18 +02001982 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001983 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001984
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001985 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001986
Paul Bakker75a28602014-03-31 12:08:17 +02001987 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001989
1990 return( ret );
1991}
1992
Paul Bakker5121ce52009-01-03 21:22:43 +00001993/*
1994 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1995 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001996int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001997{
Paul Bakker23986e52011-04-24 08:57:21 +00001998 int ret;
1999 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002000 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002001
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002002 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002003
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002004 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2005 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002006
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002007 lz = mbedtls_mpi_lsb( &TA );
2008 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002009
Paul Bakker66d5d072014-06-17 16:39:18 +02002010 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002011 lz = lzt;
2012
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002013 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2014 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002015
Paul Bakker5121ce52009-01-03 21:22:43 +00002016 TA.s = TB.s = 1;
2017
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002018 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002019 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002020 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2021 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002024 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002025 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2026 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002027 }
2028 else
2029 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002030 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2031 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002032 }
2033 }
2034
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002035 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2036 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002037
2038cleanup:
2039
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002040 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002041
2042 return( ret );
2043}
2044
Paul Bakker33dc46b2014-04-30 16:11:39 +02002045/*
2046 * Fill X with size bytes of random.
2047 *
2048 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002049 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002050 * deterministic, eg for tests).
2051 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002053 int (*f_rng)(void *, unsigned char *, size_t),
2054 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002055{
Paul Bakker23986e52011-04-24 08:57:21 +00002056 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002057 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02002058
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002059 if( size > MBEDTLS_MPI_MAX_SIZE )
2060 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002061
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002062 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2063 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002064
2065cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01002066 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002067 return( ret );
2068}
2069
Paul Bakker5121ce52009-01-03 21:22:43 +00002070/*
2071 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2072 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002073int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002074{
2075 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002077
Hanno Becker4bcb4912017-04-18 15:49:39 +01002078 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002079 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002080
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002081 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2082 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2083 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002084
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002085 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002086
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002087 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002088 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002089 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002090 goto cleanup;
2091 }
2092
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002093 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2094 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2095 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2096 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002097
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002098 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2099 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2100 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2101 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002102
2103 do
2104 {
2105 while( ( TU.p[0] & 1 ) == 0 )
2106 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002107 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002108
2109 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2110 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002111 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2112 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002113 }
2114
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002115 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2116 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002117 }
2118
2119 while( ( TV.p[0] & 1 ) == 0 )
2120 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002121 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002122
2123 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2124 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002125 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2126 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002127 }
2128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002129 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2130 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002131 }
2132
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002133 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002134 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002135 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2136 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2137 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002138 }
2139 else
2140 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002141 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2142 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2143 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002144 }
2145 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002146 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002147
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002148 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2149 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002150
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002151 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2152 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002153
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002154 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002155
2156cleanup:
2157
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002158 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2159 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2160 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002161
2162 return( ret );
2163}
2164
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002165#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002166
Paul Bakker5121ce52009-01-03 21:22:43 +00002167static const int small_prime[] =
2168{
2169 3, 5, 7, 11, 13, 17, 19, 23,
2170 29, 31, 37, 41, 43, 47, 53, 59,
2171 61, 67, 71, 73, 79, 83, 89, 97,
2172 101, 103, 107, 109, 113, 127, 131, 137,
2173 139, 149, 151, 157, 163, 167, 173, 179,
2174 181, 191, 193, 197, 199, 211, 223, 227,
2175 229, 233, 239, 241, 251, 257, 263, 269,
2176 271, 277, 281, 283, 293, 307, 311, 313,
2177 317, 331, 337, 347, 349, 353, 359, 367,
2178 373, 379, 383, 389, 397, 401, 409, 419,
2179 421, 431, 433, 439, 443, 449, 457, 461,
2180 463, 467, 479, 487, 491, 499, 503, 509,
2181 521, 523, 541, 547, 557, 563, 569, 571,
2182 577, 587, 593, 599, 601, 607, 613, 617,
2183 619, 631, 641, 643, 647, 653, 659, 661,
2184 673, 677, 683, 691, 701, 709, 719, 727,
2185 733, 739, 743, 751, 757, 761, 769, 773,
2186 787, 797, 809, 811, 821, 823, 827, 829,
2187 839, 853, 857, 859, 863, 877, 881, 883,
2188 887, 907, 911, 919, 929, 937, 941, 947,
2189 953, 967, 971, 977, 983, 991, 997, -103
2190};
2191
2192/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002193 * Small divisors test (X must be positive)
2194 *
2195 * Return values:
2196 * 0: no small factor (possible prime, more tests needed)
2197 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002199 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002200 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002201static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002202{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002203 int ret = 0;
2204 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002205 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002206
Paul Bakker5121ce52009-01-03 21:22:43 +00002207 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002208 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002209
2210 for( i = 0; small_prime[i] > 0; i++ )
2211 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002212 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002213 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002215 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002216
2217 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002218 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002219 }
2220
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002221cleanup:
2222 return( ret );
2223}
2224
2225/*
2226 * Miller-Rabin pseudo-primality test (HAC 4.24)
2227 */
Janos Follath72d555d2018-09-03 14:45:23 +01002228static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002229 int (*f_rng)(void *, unsigned char *, size_t),
2230 void *p_rng )
2231{
Pascal Junodb99183d2015-03-11 16:49:45 +01002232 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002233 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002234 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002235
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002236 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2237 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002238
Paul Bakker5121ce52009-01-03 21:22:43 +00002239 /*
2240 * W = |X| - 1
2241 * R = W >> lsb( W )
2242 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002243 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2244 s = mbedtls_mpi_lsb( &W );
2245 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2246 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002247
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002248 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002249
Janos Follath72d555d2018-09-03 14:45:23 +01002250 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002251 {
2252 /*
2253 * pick a random A, 1 < A < |X| - 1
2254 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002255 count = 0;
2256 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002257 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002258
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002259 j = mbedtls_mpi_bitlen( &A );
2260 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002261 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002262 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002263 }
2264
2265 if (count++ > 30) {
Jens Wiklanderb2aa9382019-01-17 13:30:57 +01002266 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2267 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002268 }
2269
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002270 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2271 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002272
2273 /*
2274 * A = A^R mod |X|
2275 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002276 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002277
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002278 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2279 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002280 continue;
2281
2282 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002283 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002284 {
2285 /*
2286 * A = A * A mod |X|
2287 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2289 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002290
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002291 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002292 break;
2293
2294 j++;
2295 }
2296
2297 /*
2298 * not prime if A != |X| - 1 or A == 1
2299 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002300 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2301 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002302 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002303 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002304 break;
2305 }
2306 }
2307
2308cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002309 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2310 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002311
2312 return( ret );
2313}
2314
2315/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002316 * Pseudo-primality test: small factors, then Miller-Rabin
2317 */
Darryl Green94759f62018-10-16 15:09:19 +01002318static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002319 int (*f_rng)(void *, unsigned char *, size_t),
2320 void *p_rng )
2321{
2322 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002323 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002324
2325 XX.s = 1;
2326 XX.n = X->n;
2327 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002329 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2330 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2331 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002333 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002334 return( 0 );
2335
2336 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2337 {
2338 if( ret == 1 )
2339 return( 0 );
2340
2341 return( ret );
2342 }
2343
Janos Follath72d555d2018-09-03 14:45:23 +01002344 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2345}
2346
2347/*
2348 * Pseudo-primality test, error probability 2^-80
2349 */
2350int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2351 int (*f_rng)(void *, unsigned char *, size_t),
2352 void *p_rng )
2353{
2354 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002355}
2356
2357/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002358 * Prime number generation
2359 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002360int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002361 int (*f_rng)(void *, unsigned char *, size_t),
2362 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002363{
Paul Bakker23986e52011-04-24 08:57:21 +00002364 int ret;
2365 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002366 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 mbedtls_mpi_uint r;
2368 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002370 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2371 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002372
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002373 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002374
2375 n = BITS_TO_LIMBS( nbits );
2376
Janos Follath72d555d2018-09-03 14:45:23 +01002377 /*
2378 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2379 */
2380 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2381 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2382 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2383
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002384 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002385
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002386 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002387 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002388
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002389 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002390
2391 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002392
2393 if( dh_flag == 0 )
2394 {
Janos Follath72d555d2018-09-03 14:45:23 +01002395 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002396 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002397 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002398 goto cleanup;
2399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002400 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002401 }
2402 }
2403 else
2404 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002405 /*
2406 * An necessary condition for Y and X = 2Y + 1 to be prime
2407 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2408 * Make sure it is satisfied, while keeping X = 3 mod 4
2409 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002410
2411 X->p[0] |= 2;
2412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002413 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002414 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002415 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002416 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002417 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002418
2419 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002420 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2421 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002422
2423 while( 1 )
2424 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002425 /*
2426 * First, check small factors for X and Y
2427 * before doing Miller-Rabin on any of them
2428 */
2429 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2430 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002431 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2432 == 0 &&
2433 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2434 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002435 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002436 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002437 }
2438
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002439 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002440 goto cleanup;
2441
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002442 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002443 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002444 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2445 * so up Y by 6 and X by 12.
2446 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002447 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2448 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002449 }
2450 }
2451
2452cleanup:
2453
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002454 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002455
2456 return( ret );
2457}
2458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002459#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002461#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002462
Paul Bakker23986e52011-04-24 08:57:21 +00002463#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002464
2465static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2466{
2467 { 693, 609, 21 },
2468 { 1764, 868, 28 },
2469 { 768454923, 542167814, 1 }
2470};
2471
Paul Bakker5121ce52009-01-03 21:22:43 +00002472/*
2473 * Checkup routine
2474 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002476{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002477 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002478 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002479
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002480 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2481 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002483 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002484 "EFE021C2645FD1DC586E69184AF4A31E" \
2485 "D5F53E93B5F123FA41680867BA110131" \
2486 "944FE7952E2517337780CB0DB80E61AA" \
2487 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002489 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002490 "B2E7EFD37075B9F03FF989C7C5051C20" \
2491 "34D2A323810251127E7BF8625A4F49A5" \
2492 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2493 "5B5C25763222FEFCCFC38B832366C29E" ) );
2494
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002495 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002496 "0066A198186C18C10B2F5ED9B522752A" \
2497 "9830B69916E535C8F047518A889A43A5" \
2498 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2499
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002500 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002501
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002502 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002503 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2504 "9E857EA95A03512E2BAE7391688D264A" \
2505 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2506 "8001B72E848A38CAE1C65F78E56ABDEF" \
2507 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2508 "ECF677152EF804370C1A305CAF3B5BF1" \
2509 "30879B56C61DE584A0F53A2447A51E" ) );
2510
2511 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002512 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002514 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002515 {
2516 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002517 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002518
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002519 ret = 1;
2520 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002521 }
2522
2523 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002524 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002526 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002527
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002528 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002529 "256567336059E52CAE22925474705F39A94" ) );
2530
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002531 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002532 "6613F26162223DF488E9CD48CC132C7A" \
2533 "0AC93C701B001B092E4E5B9F73BCD27B" \
2534 "9EE50D0657C77F374E903CDFA4C642" ) );
2535
2536 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002537 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002538
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002539 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2540 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002541 {
2542 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002543 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002544
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002545 ret = 1;
2546 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002547 }
2548
2549 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002550 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002552 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002554 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002555 "36E139AEA55215609D2816998ED020BB" \
2556 "BD96C37890F65171D948E9BC7CBAA4D9" \
2557 "325D24D6A3C12710F10A09FA08AB87" ) );
2558
2559 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002560 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002561
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002563 {
2564 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002565 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002566
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002567 ret = 1;
2568 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002569 }
2570
2571 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002572 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002573
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002574 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002576 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002577 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2578 "C3DBA76456363A10869622EAC2DD84EC" \
2579 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2580
2581 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002582 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002583
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002584 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002585 {
2586 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002587 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002588
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002589 ret = 1;
2590 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002591 }
2592
2593 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002594 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002595
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002596 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002597 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002598
Paul Bakker66d5d072014-06-17 16:39:18 +02002599 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002600 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002601 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2602 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002603
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002604 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002605
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002606 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002607 {
2608 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002609 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002610
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002611 ret = 1;
2612 goto cleanup;
2613 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002614 }
2615
2616 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002617 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002618
Paul Bakker5121ce52009-01-03 21:22:43 +00002619cleanup:
2620
2621 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002622 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002623
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002624 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2625 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002626
2627 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002628 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002629
2630 return( ret );
2631}
2632
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002633#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002635#endif /* MBEDTLS_BIGNUM_C */