blob: 3135ec4adc6a23367aa5f04bd6d50cac9f79a302 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Bence Szépkúti44bfbe32020-08-19 16:54:51 +02004 * Copyright The Mbed TLS Contributors
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 * **********
Paul Bakker5121ce52009-01-03 21:22:43 +000045 */
Simon Butcher15b15d12015-11-26 19:35:03 +000046
Paul Bakker5121ce52009-01-03 21:22:43 +000047/*
Simon Butcher15b15d12015-11-26 19:35:03 +000048 * The following sources were referenced in the design of this Multi-precision
49 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000050 *
Simon Butcher15b15d12015-11-26 19:35:03 +000051 * [1] Handbook of Applied Cryptography - 1997
52 * Menezes, van Oorschot and Vanstone
53 *
54 * [2] Multi-Precision Math
55 * Tom St Denis
56 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
57 *
58 * [3] GNU Multi-Precision Arithmetic Library
59 * https://gmplib.org/manual/index.html
60 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000061 */
Paul Bakker5121ce52009-01-03 21:22:43 +000062
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020063#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000064#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020065#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020066#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020067#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000068
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020069#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000070
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000071#include "mbedtls/bignum.h"
72#include "mbedtls/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000073
Rich Evans00ab4702015-02-06 13:43:58 +000074#include <string.h>
75
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020076#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000077#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020078#else
Rich Evans00ab4702015-02-06 13:43:58 +000079#include <stdio.h>
80#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020081#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020082#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020083#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020084#endif
85
Paul Bakker34617722014-06-13 17:20:13 +020086/* Implementation that should never be optimized out by the compiler */
Alexey Skalozube17a8da2016-01-13 17:19:33 +020087static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) {
Alexey Skalozub3d53f412016-01-13 16:53:40 +020088 volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0;
Paul Bakker34617722014-06-13 17:20:13 +020089}
90
Hanno Becker88807112017-10-18 12:41:30 +010091/* Implementation that should never be optimized out by the compiler */
92static void mbedtls_zeroize( void *v, size_t n ) {
93 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
94}
95
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020096#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000097#define biL (ciL << 3) /* bits in limb */
98#define biH (ciL << 2) /* half limb size */
99
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100100#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
101
Paul Bakker5121ce52009-01-03 21:22:43 +0000102/*
103 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200104 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +0000105 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200106#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
107#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +0000108
109/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000110 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000111 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200112void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000113{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000114 if( X == NULL )
115 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000116
Paul Bakker6c591fa2011-05-05 11:49:20 +0000117 X->s = 1;
118 X->n = 0;
119 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000120}
121
122/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000123 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000124 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000126{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000127 if( X == NULL )
128 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000129
Paul Bakker6c591fa2011-05-05 11:49:20 +0000130 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000131 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200132 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200133 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000134 }
135
Paul Bakker6c591fa2011-05-05 11:49:20 +0000136 X->s = 1;
137 X->n = 0;
138 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000139}
140
141/*
142 * Enlarge to the specified number of limbs
143 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000145{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000147
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200149 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000150
Paul Bakker5121ce52009-01-03 21:22:43 +0000151 if( X->n < nblimbs )
152 {
Simon Butcher29176892016-05-20 00:19:09 +0100153 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200154 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000155
Paul Bakker5121ce52009-01-03 21:22:43 +0000156 if( X->p != NULL )
157 {
158 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200159 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000161 }
162
163 X->n = nblimbs;
164 X->p = p;
165 }
166
167 return( 0 );
168}
169
170/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100171 * Resize down as much as possible,
172 * while keeping at least the specified number of limbs
173 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100177 size_t i;
178
Gilles Peskine6a269672020-01-20 21:17:43 +0100179 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100180 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine774c1632020-01-21 13:59:51 +0100182 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100183
184 for( i = X->n - 1; i > 0; i-- )
185 if( X->p[i] != 0 )
186 break;
187 i++;
188
189 if( i < nblimbs )
190 i = nblimbs;
191
Simon Butcher29176892016-05-20 00:19:09 +0100192 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200193 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100194
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100195 if( X->p != NULL )
196 {
197 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200198 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100200 }
201
202 X->n = i;
203 X->p = p;
204
205 return( 0 );
206}
207
208/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000209 * Copy the contents of Y into X
210 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000212{
Paul Bakker23986e52011-04-24 08:57:21 +0000213 int ret;
214 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000215
216 if( X == Y )
217 return( 0 );
218
Gilles Peskine2aeab872020-01-20 21:12:50 +0100219 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200220 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200222 return( 0 );
223 }
224
Paul Bakker5121ce52009-01-03 21:22:43 +0000225 for( i = Y->n - 1; i > 0; i-- )
226 if( Y->p[i] != 0 )
227 break;
228 i++;
229
230 X->s = Y->s;
231
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200232 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000233
234 memset( X->p, 0, X->n * ciL );
235 memcpy( X->p, Y->p, i * ciL );
236
237cleanup:
238
239 return( ret );
240}
241
242/*
243 * Swap the contents of X and Y
244 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200245void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000246{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000248
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249 memcpy( &T, X, sizeof( mbedtls_mpi ) );
250 memcpy( X, Y, sizeof( mbedtls_mpi ) );
251 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000252}
253
254/*
Gilles Peskine3c44c652020-06-04 19:14:58 +0200255 * Conditionally assign dest = src, without leaking information
256 * about whether the assignment was made or not.
257 * dest and src must be arrays of limbs of size n.
258 * assign must be 0 or 1.
259 */
260static void mpi_safe_cond_assign( size_t n,
261 mbedtls_mpi_uint *dest,
262 const mbedtls_mpi_uint *src,
263 unsigned char assign )
264{
265 size_t i;
266 for( i = 0; i < n; i++ )
267 dest[i] = dest[i] * ( 1 - assign ) + src[i] * assign;
268}
269
270/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100271 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100272 * about whether the assignment was made or not.
273 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100274 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200275int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100276{
277 int ret = 0;
278 size_t i;
279
Pascal Junodb99183d2015-03-11 16:49:45 +0100280 /* make sure assign is 0 or 1 in a time-constant manner */
281 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100284
Paul Bakker66d5d072014-06-17 16:39:18 +0200285 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286
Gilles Peskine3c44c652020-06-04 19:14:58 +0200287 mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100288
Gilles Peskine3c44c652020-06-04 19:14:58 +0200289 for( i = Y->n; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200290 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100291
292cleanup:
293 return( ret );
294}
295
296/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100297 * Conditionally swap X and Y, without leaking information
298 * about whether the swap was made or not.
299 * Here it is not ok to simply swap the pointers, which whould lead to
300 * different memory access patterns when X and Y are used afterwards.
301 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200302int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100303{
304 int ret, s;
305 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100307
308 if( X == Y )
309 return( 0 );
310
Pascal Junodb99183d2015-03-11 16:49:45 +0100311 /* make sure swap is 0 or 1 in a time-constant manner */
312 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100313
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200314 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
315 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100316
317 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200318 X->s = X->s * ( 1 - swap ) + Y->s * swap;
319 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100320
321
322 for( i = 0; i < X->n; i++ )
323 {
324 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200325 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
326 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100327 }
328
329cleanup:
330 return( ret );
331}
332
333/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000334 * Set value from integer
335 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000337{
338 int ret;
339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200340 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000341 memset( X->p, 0, X->n * ciL );
342
343 X->p[0] = ( z < 0 ) ? -z : z;
344 X->s = ( z < 0 ) ? -1 : 1;
345
346cleanup:
347
348 return( ret );
349}
350
351/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000352 * Get a specific bit
353 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200354int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000355{
356 if( X->n * biL <= pos )
357 return( 0 );
358
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200359 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000360}
361
Gilles Peskine220cc172018-11-20 16:47:47 +0100362/* Get a specific byte, without range checks. */
363#define GET_BYTE( X, i ) \
364 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
365
Paul Bakker2f5947e2011-05-18 15:47:11 +0000366/*
367 * Set a bit to a specific value of 0 or 1
368 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000370{
371 int ret = 0;
372 size_t off = pos / biL;
373 size_t idx = pos % biL;
374
375 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200376 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200377
Paul Bakker2f5947e2011-05-18 15:47:11 +0000378 if( X->n * biL <= pos )
379 {
380 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200381 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000384 }
385
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200386 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
387 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000388
389cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200390
Paul Bakker2f5947e2011-05-18 15:47:11 +0000391 return( ret );
392}
393
394/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200395 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000396 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000398{
Paul Bakker23986e52011-04-24 08:57:21 +0000399 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000400
401 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000402 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000403 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
404 return( count );
405
406 return( 0 );
407}
408
409/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000410 * Count leading zero bits in a given integer
411 */
412static size_t mbedtls_clz( const mbedtls_mpi_uint x )
413{
414 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100415 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000416
417 for( j = 0; j < biL; j++ )
418 {
419 if( x & mask ) break;
420
421 mask >>= 1;
422 }
423
424 return j;
425}
426
427/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200428 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000429 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200430size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000431{
Paul Bakker23986e52011-04-24 08:57:21 +0000432 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000433
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200434 if( X->n == 0 )
435 return( 0 );
436
Paul Bakker5121ce52009-01-03 21:22:43 +0000437 for( i = X->n - 1; i > 0; i-- )
438 if( X->p[i] != 0 )
439 break;
440
Simon Butcher15b15d12015-11-26 19:35:03 +0000441 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
Paul Bakker23986e52011-04-24 08:57:21 +0000443 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000444}
445
446/*
447 * Return the total size in bytes
448 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000450{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200451 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000452}
453
454/*
455 * Convert an ASCII character to digit value
456 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000458{
459 *d = 255;
460
461 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
462 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
463 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 if( *d >= (mbedtls_mpi_uint) radix )
466 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000467
468 return( 0 );
469}
470
471/*
472 * Import from an ASCII string
473 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000475{
Paul Bakker23986e52011-04-24 08:57:21 +0000476 int ret;
477 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200478 mbedtls_mpi_uint d;
479 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
481 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000485
Paul Bakkerff60ee62010-03-16 21:09:09 +0000486 slen = strlen( s );
487
Paul Bakker5121ce52009-01-03 21:22:43 +0000488 if( radix == 16 )
489 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100490 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200491 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
492
Paul Bakkerff60ee62010-03-16 21:09:09 +0000493 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200495 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
496 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000497
Paul Bakker23986e52011-04-24 08:57:21 +0000498 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000499 {
Paul Bakker23986e52011-04-24 08:57:21 +0000500 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000501 {
502 X->s = -1;
503 break;
504 }
505
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200506 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200507 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000508 }
509 }
510 else
511 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000513
Paul Bakkerff60ee62010-03-16 21:09:09 +0000514 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000515 {
516 if( i == 0 && s[i] == '-' )
517 {
518 X->s = -1;
519 continue;
520 }
521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
523 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000524
525 if( X->s == 1 )
526 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000528 }
529 else
530 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200531 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000532 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000533 }
534 }
535
536cleanup:
537
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
540 return( ret );
541}
542
543/*
Ron Eldore6cbfc32018-11-20 14:07:01 +0200544 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000545 */
Ron Eldore6cbfc32018-11-20 14:07:01 +0200546static int mpi_write_hlp( mbedtls_mpi *X, int radix,
547 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000548{
549 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550 mbedtls_mpi_uint r;
Ron Eldore6cbfc32018-11-20 14:07:01 +0200551 size_t length = 0;
552 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000553
Ron Eldore6cbfc32018-11-20 14:07:01 +0200554 do
555 {
556 if( length >= buflen )
557 {
558 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
559 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000560
Ron Eldore6cbfc32018-11-20 14:07:01 +0200561 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
562 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
563 /*
564 * Write the residue in the current position, as an ASCII character.
565 */
566 if( r < 0xA )
567 *(--p_end) = (char)( '0' + r );
568 else
569 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000570
Ron Eldore6cbfc32018-11-20 14:07:01 +0200571 length++;
572 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000573
Ron Eldore6cbfc32018-11-20 14:07:01 +0200574 memmove( *p, p_end, length );
575 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000576
577cleanup:
578
579 return( ret );
580}
581
582/*
583 * Export into an ASCII string
584 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100585int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
586 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000587{
Paul Bakker23986e52011-04-24 08:57:21 +0000588 int ret = 0;
589 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000590 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000592
593 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000595
Hanno Beckera277d4c2019-02-04 09:45:07 +0000596 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
597 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
598 * `n`. If radix > 4, this might be a strict
599 * overapproximation of the number of
600 * radix-adic digits needed to present `n`. */
601 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
602 * present `n`. */
603
Janos Follath216e7382019-03-06 13:43:02 +0000604 n += 1; /* Terminating null byte */
Hanno Beckera277d4c2019-02-04 09:45:07 +0000605 n += 1; /* Compensate for the divisions above, which round down `n`
606 * in case it's not even. */
607 n += 1; /* Potential '-'-sign. */
608 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
609 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000610
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100611 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000612 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100613 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200614 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000615 }
616
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100617 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200618 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000619
620 if( X->s == -1 )
Hanno Beckereff335d2019-02-01 16:41:30 +0000621 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000622 *p++ = '-';
Hanno Beckereff335d2019-02-01 16:41:30 +0000623 buflen--;
624 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000625
626 if( radix == 16 )
627 {
Paul Bakker23986e52011-04-24 08:57:21 +0000628 int c;
629 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000630
Paul Bakker23986e52011-04-24 08:57:21 +0000631 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000632 {
Paul Bakker23986e52011-04-24 08:57:21 +0000633 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000634 {
Paul Bakker23986e52011-04-24 08:57:21 +0000635 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000636
Paul Bakker6c343d72014-07-10 14:36:19 +0200637 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000638 continue;
639
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000640 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000641 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000642 k = 1;
643 }
644 }
645 }
646 else
647 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000649
650 if( T.s == -1 )
651 T.s = 1;
652
Ron Eldore6cbfc32018-11-20 14:07:01 +0200653 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000654 }
655
656 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100657 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000658
659cleanup:
660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000662
663 return( ret );
664}
665
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000667/*
668 * Read X from an opened file
669 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000671{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000673 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000674 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000675 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000676 * Buffer should have space for (short) label and decimal formatted MPI,
677 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000678 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200679 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000680
681 memset( s, 0, sizeof( s ) );
682 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000684
685 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000686 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000688
Hanno Beckerb2034b72017-04-26 11:46:46 +0100689 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
690 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
692 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100693 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000694 if( mpi_get_digit( &d, radix, *p ) != 0 )
695 break;
696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000698}
699
700/*
701 * Write X into an opened file (or stdout if fout == NULL)
702 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000704{
Paul Bakker23986e52011-04-24 08:57:21 +0000705 int ret;
706 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000707 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000708 * Buffer should have space for (short) label and decimal formatted MPI,
709 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000710 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200711 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000712
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100713 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000714
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100715 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000716
717 if( p == NULL ) p = "";
718
719 plen = strlen( p );
720 slen = strlen( s );
721 s[slen++] = '\r';
722 s[slen++] = '\n';
723
724 if( fout != NULL )
725 {
726 if( fwrite( p, 1, plen, fout ) != plen ||
727 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000729 }
730 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000732
733cleanup:
734
735 return( ret );
736}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000738
739/*
740 * Import X from unsigned binary data, big endian
741 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200742int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000743{
Paul Bakker23986e52011-04-24 08:57:21 +0000744 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100745 size_t i, j;
746 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000747
Hanno Becker073c1992017-10-17 15:17:27 +0100748 /* Ensure that target MPI has exactly the necessary number of limbs */
749 if( X->n != limbs )
750 {
751 mbedtls_mpi_free( X );
752 mbedtls_mpi_init( X );
753 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
754 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000755
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200756 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000757
Hanno Becker073c1992017-10-17 15:17:27 +0100758 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200759 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000760
761cleanup:
762
763 return( ret );
764}
765
766/*
767 * Export X into unsigned binary data, big endian
768 */
Gilles Peskine220cc172018-11-20 16:47:47 +0100769int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
770 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000771{
Gilles Peskine220cc172018-11-20 16:47:47 +0100772 size_t stored_bytes = X->n * ciL;
773 size_t bytes_to_copy;
774 unsigned char *p;
775 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000776
Gilles Peskine220cc172018-11-20 16:47:47 +0100777 if( stored_bytes < buflen )
778 {
779 /* There is enough space in the output buffer. Write initial
780 * null bytes and record the position at which to start
781 * writing the significant bytes. In this case, the execution
782 * trace of this function does not depend on the value of the
783 * number. */
784 bytes_to_copy = stored_bytes;
785 p = buf + buflen - stored_bytes;
786 memset( buf, 0, buflen - stored_bytes );
787 }
788 else
789 {
790 /* The output buffer is smaller than the allocated size of X.
791 * However X may fit if its leading bytes are zero. */
792 bytes_to_copy = buflen;
793 p = buf;
794 for( i = bytes_to_copy; i < stored_bytes; i++ )
795 {
796 if( GET_BYTE( X, i ) != 0 )
797 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
798 }
799 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000800
Gilles Peskine220cc172018-11-20 16:47:47 +0100801 for( i = 0; i < bytes_to_copy; i++ )
802 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000803
804 return( 0 );
805}
806
807/*
808 * Left-shift: X <<= count
809 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200810int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000811{
Paul Bakker23986e52011-04-24 08:57:21 +0000812 int ret;
813 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200814 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000815
816 v0 = count / (biL );
817 t1 = count & (biL - 1);
818
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200819 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000820
Paul Bakkerf9688572011-05-05 10:00:45 +0000821 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200822 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000823
824 ret = 0;
825
826 /*
827 * shift by count / limb_size
828 */
829 if( v0 > 0 )
830 {
Paul Bakker23986e52011-04-24 08:57:21 +0000831 for( i = X->n; i > v0; i-- )
832 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000833
Paul Bakker23986e52011-04-24 08:57:21 +0000834 for( ; i > 0; i-- )
835 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000836 }
837
838 /*
839 * shift by count % limb_size
840 */
841 if( t1 > 0 )
842 {
843 for( i = v0; i < X->n; i++ )
844 {
845 r1 = X->p[i] >> (biL - t1);
846 X->p[i] <<= t1;
847 X->p[i] |= r0;
848 r0 = r1;
849 }
850 }
851
852cleanup:
853
854 return( ret );
855}
856
857/*
858 * Right-shift: X >>= count
859 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200860int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000861{
Paul Bakker23986e52011-04-24 08:57:21 +0000862 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200863 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000864
865 v0 = count / biL;
866 v1 = count & (biL - 1);
867
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100868 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200869 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100870
Paul Bakker5121ce52009-01-03 21:22:43 +0000871 /*
872 * shift by count / limb_size
873 */
874 if( v0 > 0 )
875 {
876 for( i = 0; i < X->n - v0; i++ )
877 X->p[i] = X->p[i + v0];
878
879 for( ; i < X->n; i++ )
880 X->p[i] = 0;
881 }
882
883 /*
884 * shift by count % limb_size
885 */
886 if( v1 > 0 )
887 {
Paul Bakker23986e52011-04-24 08:57:21 +0000888 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000889 {
Paul Bakker23986e52011-04-24 08:57:21 +0000890 r1 = X->p[i - 1] << (biL - v1);
891 X->p[i - 1] >>= v1;
892 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000893 r0 = r1;
894 }
895 }
896
897 return( 0 );
898}
899
900/*
901 * Compare unsigned values
902 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200903int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000904{
Paul Bakker23986e52011-04-24 08:57:21 +0000905 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000906
Paul Bakker23986e52011-04-24 08:57:21 +0000907 for( i = X->n; i > 0; i-- )
908 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000909 break;
910
Paul Bakker23986e52011-04-24 08:57:21 +0000911 for( j = Y->n; j > 0; j-- )
912 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000913 break;
914
Paul Bakker23986e52011-04-24 08:57:21 +0000915 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000916 return( 0 );
917
918 if( i > j ) return( 1 );
919 if( j > i ) return( -1 );
920
Paul Bakker23986e52011-04-24 08:57:21 +0000921 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000922 {
Paul Bakker23986e52011-04-24 08:57:21 +0000923 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
924 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000925 }
926
927 return( 0 );
928}
929
930/*
931 * Compare signed values
932 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200933int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000934{
Paul Bakker23986e52011-04-24 08:57:21 +0000935 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000936
Paul Bakker23986e52011-04-24 08:57:21 +0000937 for( i = X->n; i > 0; i-- )
938 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000939 break;
940
Paul Bakker23986e52011-04-24 08:57:21 +0000941 for( j = Y->n; j > 0; j-- )
942 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000943 break;
944
Paul Bakker23986e52011-04-24 08:57:21 +0000945 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000946 return( 0 );
947
948 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000949 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000950
951 if( X->s > 0 && Y->s < 0 ) return( 1 );
952 if( Y->s > 0 && X->s < 0 ) return( -1 );
953
Paul Bakker23986e52011-04-24 08:57:21 +0000954 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000955 {
Paul Bakker23986e52011-04-24 08:57:21 +0000956 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
957 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000958 }
959
960 return( 0 );
961}
962
Janos Follath3173a532019-10-14 09:09:32 +0100963/** Decide if an integer is less than the other, without branches.
964 *
965 * \param x First integer.
966 * \param y Second integer.
967 *
968 * \return 1 if \p x is less than \p y, 0 otherwise
969 */
Janos Follathc3b376e2019-10-11 14:21:53 +0100970static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
971 const mbedtls_mpi_uint y )
Janos Follathe0187b92019-09-05 14:47:19 +0100972{
973 mbedtls_mpi_uint ret;
974 mbedtls_mpi_uint cond;
975
976 /*
977 * Check if the most significant bits (MSB) of the operands are different.
978 */
979 cond = ( x ^ y );
980 /*
981 * If the MSB are the same then the difference x-y will be negative (and
982 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
983 */
984 ret = ( x - y ) & ~cond;
985 /*
986 * If the MSB are different, then the operand with the MSB of 1 is the
987 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
988 * the MSB of y is 0.)
989 */
990 ret |= y & cond;
991
992
Janos Follathdb9f4492019-10-14 08:59:14 +0100993 ret = ret >> ( biL - 1 );
Janos Follathe0187b92019-09-05 14:47:19 +0100994
Janos Follath58239612019-10-29 15:08:46 +0000995 return (unsigned) ret;
Janos Follathe0187b92019-09-05 14:47:19 +0100996}
997
998/*
999 * Compare signed values in constant time
1000 */
Janos Follathc3b376e2019-10-11 14:21:53 +01001001int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1002 unsigned *ret )
Janos Follathe0187b92019-09-05 14:47:19 +01001003{
1004 size_t i;
Janos Follatha2b9a962019-10-28 12:23:18 +00001005 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath8ec2a952019-10-28 12:31:34 +00001006 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathe0187b92019-09-05 14:47:19 +01001007
1008 if( X->n != Y->n )
1009 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1010
1011 /*
Janos Follath51ed14e2019-10-28 12:12:15 +00001012 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1013 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathe0187b92019-09-05 14:47:19 +01001014 */
Janos Follath8ec2a952019-10-28 12:31:34 +00001015 X_is_negative = ( X->s & 2 ) >> 1;
1016 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follathc3b376e2019-10-11 14:21:53 +01001017
1018 /*
1019 * If the signs are different, then the positive operand is the bigger.
Janos Follath8ec2a952019-10-28 12:31:34 +00001020 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1021 * is false if X is positive (X_is_negative == 0).
Janos Follathc3b376e2019-10-11 14:21:53 +01001022 */
Janos Follath8ec2a952019-10-28 12:31:34 +00001023 cond = ( X_is_negative ^ Y_is_negative );
1024 *ret = cond & X_is_negative;
Janos Follathc3b376e2019-10-11 14:21:53 +01001025
1026 /*
Janos Follatha2b9a962019-10-28 12:23:18 +00001027 * This is a constant-time function. We might have the result, but we still
Janos Follathc3b376e2019-10-11 14:21:53 +01001028 * need to go through the loop. Record if we have the result already.
1029 */
Janos Follathe0187b92019-09-05 14:47:19 +01001030 done = cond;
1031
1032 for( i = X->n; i > 0; i-- )
1033 {
1034 /*
Janos Follathb4edac52019-11-05 12:24:52 +00001035 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1036 * X and Y are negative.
Janos Follathc3b376e2019-10-11 14:21:53 +01001037 *
1038 * Again even if we can make a decision, we just mark the result and
1039 * the fact that we are done and continue looping.
Janos Follathe0187b92019-09-05 14:47:19 +01001040 */
Janos Follathb4edac52019-11-05 12:24:52 +00001041 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1042 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathcff9e6e2019-10-28 12:37:21 +00001043 done |= cond;
Janos Follathe0187b92019-09-05 14:47:19 +01001044
1045 /*
Janos Follathb4edac52019-11-05 12:24:52 +00001046 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1047 * X and Y are positive.
Janos Follathc3b376e2019-10-11 14:21:53 +01001048 *
1049 * Again even if we can make a decision, we just mark the result and
1050 * the fact that we are done and continue looping.
Janos Follathe0187b92019-09-05 14:47:19 +01001051 */
Janos Follathb4edac52019-11-05 12:24:52 +00001052 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1053 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathcff9e6e2019-10-28 12:37:21 +00001054 done |= cond;
Janos Follathe0187b92019-09-05 14:47:19 +01001055 }
1056
1057 return( 0 );
1058}
1059
Paul Bakker5121ce52009-01-03 21:22:43 +00001060/*
1061 * Compare signed values
1062 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001063int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001064{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001065 mbedtls_mpi Y;
1066 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001067
1068 *p = ( z < 0 ) ? -z : z;
1069 Y.s = ( z < 0 ) ? -1 : 1;
1070 Y.n = 1;
1071 Y.p = p;
1072
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001073 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001074}
1075
1076/*
1077 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1078 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001079int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001080{
Paul Bakker23986e52011-04-24 08:57:21 +00001081 int ret;
1082 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001083 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +00001084
1085 if( X == B )
1086 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001087 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001088 }
1089
1090 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001091 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001092
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001093 /*
1094 * X should always be positive as a result of unsigned additions.
1095 */
1096 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001097
Paul Bakker23986e52011-04-24 08:57:21 +00001098 for( j = B->n; j > 0; j-- )
1099 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001100 break;
1101
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001102 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001103
1104 o = B->p; p = X->p; c = 0;
1105
Janos Follath6c922682015-10-30 17:43:11 +01001106 /*
1107 * tmp is used because it might happen that p == o
1108 */
Paul Bakker23986e52011-04-24 08:57:21 +00001109 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001110 {
Janos Follath6c922682015-10-30 17:43:11 +01001111 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001112 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001113 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001114 }
1115
1116 while( c != 0 )
1117 {
1118 if( i >= X->n )
1119 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001120 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001121 p = X->p + i;
1122 }
1123
Paul Bakker2d319fd2012-09-16 21:34:26 +00001124 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001125 }
1126
1127cleanup:
1128
1129 return( ret );
1130}
1131
Gilles Peskinef3317e62020-06-09 10:39:38 +02001132/**
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001133 * Helper for mbedtls_mpi subtraction.
1134 *
1135 * Calculate d - s where d and s have the same size.
1136 * This function operates modulo (2^ciL)^n and returns the carry
1137 * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise).
1138 *
1139 * \param n Number of limbs of \p d and \p s.
1140 * \param[in,out] d On input, the left operand.
1141 * On output, the result of the subtraction:
Gilles Peskinef3317e62020-06-09 10:39:38 +02001142 * \param[in] s The right operand.
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001143 *
1144 * \return 1 if `d < s`.
1145 * 0 if `d >= s`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001146 */
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001147static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1148 mbedtls_mpi_uint *d,
1149 const mbedtls_mpi_uint *s )
Paul Bakker5121ce52009-01-03 21:22:43 +00001150{
Paul Bakker23986e52011-04-24 08:57:21 +00001151 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001152 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001153
1154 for( i = c = 0; i < n; i++, s++, d++ )
1155 {
1156 z = ( *d < c ); *d -= c;
1157 c = ( *d < *s ) + z; *d -= *s;
1158 }
1159
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001160 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001161}
1162
1163/*
Gilles Peskinefa85cc22020-06-08 22:50:35 +02001164 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001165 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001166int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001167{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001168 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001169 int ret;
1170 size_t n;
Gilles Peskinefa85cc22020-06-08 22:50:35 +02001171 mbedtls_mpi_uint carry;
Paul Bakker5121ce52009-01-03 21:22:43 +00001172
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001173 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001174
1175 if( X == B )
1176 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001177 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001178 B = &TB;
1179 }
1180
1181 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001182 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001183
Paul Bakker1ef7a532009-06-20 10:50:55 +00001184 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001185 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001186 */
1187 X->s = 1;
1188
Paul Bakker5121ce52009-01-03 21:22:43 +00001189 ret = 0;
1190
Paul Bakker23986e52011-04-24 08:57:21 +00001191 for( n = B->n; n > 0; n-- )
1192 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001193 break;
1194
Gilles Peskinefa85cc22020-06-08 22:50:35 +02001195 carry = mpi_sub_hlp( n, X->p, B->p );
1196 if( carry != 0 )
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001197 {
Gilles Peskinefa85cc22020-06-08 22:50:35 +02001198 /* Propagate the carry to the first nonzero limb of X. */
1199 for( ; n < X->n && X->p[n] == 0; n++ )
1200 --X->p[n];
1201 /* If we ran out of space for the carry, it means that the result
1202 * is negative. */
1203 if( n == X->n )
1204 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
1205 --X->p[n];
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001206 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001207
1208cleanup:
1209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001210 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001211
1212 return( ret );
1213}
1214
1215/*
1216 * Signed addition: X = A + B
1217 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001218int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001219{
1220 int ret, s = A->s;
1221
1222 if( A->s * B->s < 0 )
1223 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001224 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001225 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001226 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001227 X->s = s;
1228 }
1229 else
1230 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001231 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001232 X->s = -s;
1233 }
1234 }
1235 else
1236 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001237 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001238 X->s = s;
1239 }
1240
1241cleanup:
1242
1243 return( ret );
1244}
1245
1246/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001247 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001248 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001249int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001250{
1251 int ret, s = A->s;
1252
1253 if( A->s * B->s > 0 )
1254 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001255 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001256 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001257 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001258 X->s = s;
1259 }
1260 else
1261 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001262 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001263 X->s = -s;
1264 }
1265 }
1266 else
1267 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001268 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001269 X->s = s;
1270 }
1271
1272cleanup:
1273
1274 return( ret );
1275}
1276
1277/*
1278 * Signed addition: X = A + b
1279 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001280int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001281{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001282 mbedtls_mpi _B;
1283 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001284
1285 p[0] = ( b < 0 ) ? -b : b;
1286 _B.s = ( b < 0 ) ? -1 : 1;
1287 _B.n = 1;
1288 _B.p = p;
1289
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001290 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001291}
1292
1293/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001294 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001295 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001296int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001297{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001298 mbedtls_mpi _B;
1299 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001300
1301 p[0] = ( b < 0 ) ? -b : b;
1302 _B.s = ( b < 0 ) ? -1 : 1;
1303 _B.n = 1;
1304 _B.p = p;
1305
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001306 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001307}
1308
1309/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001310 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001311 */
1312static
1313#if defined(__APPLE__) && defined(__arm__)
1314/*
1315 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1316 * appears to need this to prevent bad ARM code generation at -O3.
1317 */
1318__attribute__ ((noinline))
1319#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001320void 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 +00001321{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001322 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001323
1324#if defined(MULADDC_HUIT)
1325 for( ; i >= 8; i -= 8 )
1326 {
1327 MULADDC_INIT
1328 MULADDC_HUIT
1329 MULADDC_STOP
1330 }
1331
1332 for( ; i > 0; i-- )
1333 {
1334 MULADDC_INIT
1335 MULADDC_CORE
1336 MULADDC_STOP
1337 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001338#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001339 for( ; i >= 16; i -= 16 )
1340 {
1341 MULADDC_INIT
1342 MULADDC_CORE MULADDC_CORE
1343 MULADDC_CORE MULADDC_CORE
1344 MULADDC_CORE MULADDC_CORE
1345 MULADDC_CORE MULADDC_CORE
1346
1347 MULADDC_CORE MULADDC_CORE
1348 MULADDC_CORE MULADDC_CORE
1349 MULADDC_CORE MULADDC_CORE
1350 MULADDC_CORE MULADDC_CORE
1351 MULADDC_STOP
1352 }
1353
1354 for( ; i >= 8; i -= 8 )
1355 {
1356 MULADDC_INIT
1357 MULADDC_CORE MULADDC_CORE
1358 MULADDC_CORE MULADDC_CORE
1359
1360 MULADDC_CORE MULADDC_CORE
1361 MULADDC_CORE MULADDC_CORE
1362 MULADDC_STOP
1363 }
1364
1365 for( ; i > 0; i-- )
1366 {
1367 MULADDC_INIT
1368 MULADDC_CORE
1369 MULADDC_STOP
1370 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001371#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001372
1373 t++;
1374
1375 do {
1376 *d += c; c = ( *d < c ); d++;
1377 }
1378 while( c != 0 );
1379}
1380
1381/*
1382 * Baseline multiplication: X = A * B (HAC 14.12)
1383 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001384int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001385{
Paul Bakker23986e52011-04-24 08:57:21 +00001386 int ret;
1387 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001388 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1393 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001394
Paul Bakker23986e52011-04-24 08:57:21 +00001395 for( i = A->n; i > 0; i-- )
1396 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001397 break;
1398
Paul Bakker23986e52011-04-24 08:57:21 +00001399 for( j = B->n; j > 0; j-- )
1400 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001401 break;
1402
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1404 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001405
Paul Bakker23986e52011-04-24 08:57:21 +00001406 for( i++; j > 0; j-- )
1407 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001408
1409 X->s = A->s * B->s;
1410
1411cleanup:
1412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001413 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001414
1415 return( ret );
1416}
1417
1418/*
1419 * Baseline multiplication: X = A * b
1420 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001421int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001422{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001423 mbedtls_mpi _B;
1424 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001425
1426 _B.s = 1;
1427 _B.n = 1;
1428 _B.p = p;
1429 p[0] = b;
1430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001431 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001432}
1433
1434/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001435 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1436 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001437 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001438static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1439 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001440{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001441#if defined(MBEDTLS_HAVE_UDBL)
1442 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001443#else
Simon Butcher9803d072016-01-03 00:24:34 +00001444 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1445 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001446 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1447 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001448 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001449#endif
1450
Simon Butcher15b15d12015-11-26 19:35:03 +00001451 /*
1452 * Check for overflow
1453 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001454 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001455 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001456 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001457
Simon Butcherf5ba0452015-12-27 23:01:55 +00001458 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001459 }
1460
1461#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001462 dividend = (mbedtls_t_udbl) u1 << biL;
1463 dividend |= (mbedtls_t_udbl) u0;
1464 quotient = dividend / d;
1465 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1466 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1467
1468 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001469 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001470
1471 return (mbedtls_mpi_uint) quotient;
1472#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001473
1474 /*
1475 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1476 * Vol. 2 - Seminumerical Algorithms, Knuth
1477 */
1478
1479 /*
1480 * Normalize the divisor, d, and dividend, u0, u1
1481 */
1482 s = mbedtls_clz( d );
1483 d = d << s;
1484
1485 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001486 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001487 u0 = u0 << s;
1488
1489 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001490 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001491
1492 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001493 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001494
1495 /*
1496 * Find the first quotient and remainder
1497 */
1498 q1 = u1 / d1;
1499 r0 = u1 - d1 * q1;
1500
1501 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1502 {
1503 q1 -= 1;
1504 r0 += d1;
1505
1506 if ( r0 >= radix ) break;
1507 }
1508
Simon Butcherf5ba0452015-12-27 23:01:55 +00001509 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001510 q0 = rAX / d1;
1511 r0 = rAX - q0 * d1;
1512
1513 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1514 {
1515 q0 -= 1;
1516 r0 += d1;
1517
1518 if ( r0 >= radix ) break;
1519 }
1520
1521 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001522 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001523
1524 quotient = q1 * radix + q0;
1525
1526 return quotient;
1527#endif
1528}
1529
1530/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001531 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001532 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001533int 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 +00001534{
Paul Bakker23986e52011-04-24 08:57:21 +00001535 int ret;
1536 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001537 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001538
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1540 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001541
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001542 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1543 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001544
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001545 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001546 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001547 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1548 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001549 return( 0 );
1550 }
1551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001552 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1553 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001554 X.s = Y.s = 1;
1555
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001556 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1557 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1558 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1559 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001560
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001561 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001562 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001563 {
1564 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001565 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1566 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001567 }
1568 else k = 0;
1569
1570 n = X.n - 1;
1571 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001572 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001573
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001574 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001575 {
1576 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001577 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001578 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001579 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001580
1581 for( i = n; i > t ; i-- )
1582 {
1583 if( X.p[i] >= Y.p[t] )
1584 Z.p[i - t - 1] = ~0;
1585 else
1586 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001587 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1588 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001589 }
1590
1591 Z.p[i - t - 1]++;
1592 do
1593 {
1594 Z.p[i - t - 1]--;
1595
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001596 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001597 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001598 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001599 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001600
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001601 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001602 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1603 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001604 T2.p[2] = X.p[i];
1605 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001606 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001607
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001608 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1609 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1610 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001612 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001613 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001614 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1615 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1616 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001617 Z.p[i - t - 1]--;
1618 }
1619 }
1620
1621 if( Q != NULL )
1622 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001623 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001624 Q->s = A->s * B->s;
1625 }
1626
1627 if( R != NULL )
1628 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001629 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001630 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001631 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001632
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001633 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001634 R->s = 1;
1635 }
1636
1637cleanup:
1638
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001639 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1640 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001641
1642 return( ret );
1643}
1644
1645/*
1646 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001647 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001648int 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 +00001649{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001650 mbedtls_mpi _B;
1651 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001652
1653 p[0] = ( b < 0 ) ? -b : b;
1654 _B.s = ( b < 0 ) ? -1 : 1;
1655 _B.n = 1;
1656 _B.p = p;
1657
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001658 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001659}
1660
1661/*
1662 * Modulo: R = A mod B
1663 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001664int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001665{
1666 int ret;
1667
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001668 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1669 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001670
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001672
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001673 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1674 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001676 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1677 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001678
1679cleanup:
1680
1681 return( ret );
1682}
1683
1684/*
1685 * Modulo: r = A mod b
1686 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001687int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001688{
Paul Bakker23986e52011-04-24 08:57:21 +00001689 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001690 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001691
1692 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001693 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001694
1695 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001696 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001697
1698 /*
1699 * handle trivial cases
1700 */
1701 if( b == 1 )
1702 {
1703 *r = 0;
1704 return( 0 );
1705 }
1706
1707 if( b == 2 )
1708 {
1709 *r = A->p[0] & 1;
1710 return( 0 );
1711 }
1712
1713 /*
1714 * general case
1715 */
Paul Bakker23986e52011-04-24 08:57:21 +00001716 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001717 {
Paul Bakker23986e52011-04-24 08:57:21 +00001718 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001719 y = ( y << biH ) | ( x >> biH );
1720 z = y / b;
1721 y -= z * b;
1722
1723 x <<= biH;
1724 y = ( y << biH ) | ( x >> biH );
1725 z = y / b;
1726 y -= z * b;
1727 }
1728
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001729 /*
1730 * If A is negative, then the current y represents a negative value.
1731 * Flipping it to the positive side.
1732 */
1733 if( A->s < 0 && y != 0 )
1734 y = b - y;
1735
Paul Bakker5121ce52009-01-03 21:22:43 +00001736 *r = y;
1737
1738 return( 0 );
1739}
1740
1741/*
1742 * Fast Montgomery initialization (thanks to Tom St Denis)
1743 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001744static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001745{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001746 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001747 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001748
1749 x = m0;
1750 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001751
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001752 for( i = biL; i >= 8; i /= 2 )
1753 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001754
1755 *mm = ~x + 1;
1756}
1757
Gilles Peskined108d072020-06-04 15:00:49 +02001758/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1759 *
1760 * \param[in,out] A One of the numbers to multiply.
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001761 * It must have at least as many limbs as N
1762 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskined108d072020-06-04 15:00:49 +02001763 * On successful completion, A contains the result of
1764 * the multiplication A * B * R^-1 mod N where
1765 * R = (2^ciL)^n.
1766 * \param[in] B One of the numbers to multiply.
1767 * It must be nonzero and must not have more limbs than N
1768 * (B->n <= N->n).
1769 * \param[in] N The modulo. N must be odd.
1770 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1771 * This is -N^-1 mod 2^ciL.
1772 * \param[in,out] T A bignum for temporary storage.
1773 * It must be at least twice the limb size of N plus 2
1774 * (T->n >= 2 * (N->n + 1)).
1775 * Its initial content is unused and
1776 * its final content is indeterminate.
1777 * Note that unlike the usual convention in the library
1778 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00001779 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001780static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001781 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001782{
Paul Bakker23986e52011-04-24 08:57:21 +00001783 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001784 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001785
1786 memset( T->p, 0, T->n * ciL );
1787
1788 d = T->p;
1789 n = N->n;
1790 m = ( B->n < n ) ? B->n : n;
1791
1792 for( i = 0; i < n; i++ )
1793 {
1794 /*
1795 * T = (T + u0*B + u1*N) / 2^biL
1796 */
1797 u0 = A->p[i];
1798 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1799
1800 mpi_mul_hlp( m, B->p, d, u0 );
1801 mpi_mul_hlp( n, N->p, d, u1 );
1802
1803 *d++ = u0; d[n + 1] = 0;
1804 }
1805
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001806 /* At this point, d is either the desired result or the desired result
1807 * plus N. We now potentially subtract N, avoiding leaking whether the
1808 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001809
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001810 /* Copy the n least significant limbs of d to A, so that
1811 * A = d if d < N (recall that N has n limbs). */
1812 memcpy( A->p, d, n * ciL );
Gilles Peskinef3317e62020-06-09 10:39:38 +02001813 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001814 * do the calculation without using conditional tests. */
1815 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine7ff812e2020-06-04 21:05:24 +02001816 d[n] += 1;
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001817 d[n] -= mpi_sub_hlp( n, d, N->p );
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001818 /* If d0 < N then d < (2^biL)^n
1819 * so d[n] == 0 and we want to keep A as it is.
1820 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
1821 * so d[n] == 1 and we want to set A to the result of the subtraction
1822 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
1823 * This exactly corresponds to a conditional assignment. */
1824 mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001825}
1826
1827/*
1828 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskined108d072020-06-04 15:00:49 +02001829 *
1830 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001831 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001832static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001833{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001834 mbedtls_mpi_uint z = 1;
1835 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001836
Paul Bakker8ddb6452013-02-27 14:56:33 +01001837 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001838 U.p = &z;
1839
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001840 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001841}
1842
1843/*
1844 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1845 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001846int 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 +00001847{
Paul Bakker23986e52011-04-24 08:57:21 +00001848 int ret;
1849 size_t wbits, wsize, one = 1;
1850 size_t i, j, nblimbs;
1851 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001852 mbedtls_mpi_uint ei, mm, state;
1853 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001854 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001855
Hanno Becker930ec7d2018-03-09 10:48:00 +00001856 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001857 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001858
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001859 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1860 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001861
1862 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001863 * Init temps and window size
1864 */
1865 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001866 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1867 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001868 memset( W, 0, sizeof( W ) );
1869
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001870 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001871
1872 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1873 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1874
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001875#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001876 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1877 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001878#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001879
Paul Bakker5121ce52009-01-03 21:22:43 +00001880 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001881 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1882 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1883 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001884
1885 /*
Paul Bakker50546922012-05-19 08:40:49 +00001886 * Compensate for negative A (and correct at the end)
1887 */
1888 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001889 if( neg )
1890 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001891 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001892 Apos.s = 1;
1893 A = &Apos;
1894 }
1895
1896 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001897 * If 1st call, pre-compute R^2 mod N
1898 */
1899 if( _RR == NULL || _RR->p == NULL )
1900 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001901 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1902 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1903 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001904
1905 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001906 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001907 }
1908 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001909 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001910
1911 /*
1912 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1913 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001914 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1915 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001916 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001917 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001918
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001919 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001920
1921 /*
1922 * X = R^2 * R^-1 mod N = R mod N
1923 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001924 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001925 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001926
1927 if( wsize > 1 )
1928 {
1929 /*
1930 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1931 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001932 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001933
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001934 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1935 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001936
1937 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001938 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001939
Paul Bakker5121ce52009-01-03 21:22:43 +00001940 /*
1941 * W[i] = W[i - 1] * W[1]
1942 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001943 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001944 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001945 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1946 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001947
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001948 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001949 }
1950 }
1951
1952 nblimbs = E->n;
1953 bufsize = 0;
1954 nbits = 0;
1955 wbits = 0;
1956 state = 0;
1957
1958 while( 1 )
1959 {
1960 if( bufsize == 0 )
1961 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001962 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001963 break;
1964
Paul Bakker0d7702c2013-10-29 16:18:35 +01001965 nblimbs--;
1966
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001967 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001968 }
1969
1970 bufsize--;
1971
1972 ei = (E->p[nblimbs] >> bufsize) & 1;
1973
1974 /*
1975 * skip leading 0s
1976 */
1977 if( ei == 0 && state == 0 )
1978 continue;
1979
1980 if( ei == 0 && state == 1 )
1981 {
1982 /*
1983 * out of window, square X
1984 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001985 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001986 continue;
1987 }
1988
1989 /*
1990 * add ei to current window
1991 */
1992 state = 2;
1993
1994 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001995 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001996
1997 if( nbits == wsize )
1998 {
1999 /*
2000 * X = X^wsize R^-1 mod N
2001 */
2002 for( i = 0; i < wsize; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002003 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002004
2005 /*
2006 * X = X * W[wbits] R^-1 mod N
2007 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002008 mpi_montmul( X, &W[wbits], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002009
2010 state--;
2011 nbits = 0;
2012 wbits = 0;
2013 }
2014 }
2015
2016 /*
2017 * process the remaining bits
2018 */
2019 for( i = 0; i < nbits; i++ )
2020 {
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002021 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
2023 wbits <<= 1;
2024
Paul Bakker66d5d072014-06-17 16:39:18 +02002025 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002026 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002027 }
2028
2029 /*
2030 * X = A^E * R * R^-1 mod N = A^E mod N
2031 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002032 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002033
Hanno Beckera4af1c42017-04-18 09:07:45 +01002034 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002035 {
2036 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002037 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002038 }
2039
Paul Bakker5121ce52009-01-03 21:22:43 +00002040cleanup:
2041
Paul Bakker66d5d072014-06-17 16:39:18 +02002042 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002043 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002044
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002045 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002046
Paul Bakker75a28602014-03-31 12:08:17 +02002047 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002048 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002049
2050 return( ret );
2051}
2052
Paul Bakker5121ce52009-01-03 21:22:43 +00002053/*
2054 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2055 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002056int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002057{
Paul Bakker23986e52011-04-24 08:57:21 +00002058 int ret;
2059 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002061
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002062 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002063
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002064 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2065 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002066
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002067 lz = mbedtls_mpi_lsb( &TA );
2068 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002069
Paul Bakker66d5d072014-06-17 16:39:18 +02002070 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002071 lz = lzt;
2072
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002073 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2074 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002075
Paul Bakker5121ce52009-01-03 21:22:43 +00002076 TA.s = TB.s = 1;
2077
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002078 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002079 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002080 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2081 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002082
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002083 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002084 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002085 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2086 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002087 }
2088 else
2089 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002090 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2091 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002092 }
2093 }
2094
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002095 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2096 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002097
2098cleanup:
2099
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002100 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002101
2102 return( ret );
2103}
2104
Paul Bakker33dc46b2014-04-30 16:11:39 +02002105/*
2106 * Fill X with size bytes of random.
2107 *
2108 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002109 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002110 * deterministic, eg for tests).
2111 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002112int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002113 int (*f_rng)(void *, unsigned char *, size_t),
2114 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002115{
Paul Bakker23986e52011-04-24 08:57:21 +00002116 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002117 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02002118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002119 if( size > MBEDTLS_MPI_MAX_SIZE )
2120 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002121
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002122 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2123 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002124
2125cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01002126 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002127 return( ret );
2128}
2129
Paul Bakker5121ce52009-01-03 21:22:43 +00002130/*
2131 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2132 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002133int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002134{
2135 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002136 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002137
Hanno Becker4bcb4912017-04-18 15:49:39 +01002138 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002139 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002140
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002141 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2142 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2143 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002146
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002147 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002148 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002149 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002150 goto cleanup;
2151 }
2152
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002153 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2154 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2155 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2156 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002157
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002158 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2159 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2160 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2161 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002162
2163 do
2164 {
2165 while( ( TU.p[0] & 1 ) == 0 )
2166 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002167 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002168
2169 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2170 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002171 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2172 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002173 }
2174
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002175 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2176 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002177 }
2178
2179 while( ( TV.p[0] & 1 ) == 0 )
2180 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002181 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002182
2183 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2184 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002185 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2186 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002187 }
2188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002189 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2190 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002191 }
2192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002193 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002194 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002195 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2196 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2197 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002198 }
2199 else
2200 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002201 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2202 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2203 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002204 }
2205 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002207
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002208 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2209 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002210
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002211 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2212 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002213
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002214 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002215
2216cleanup:
2217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002218 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2219 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2220 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002221
2222 return( ret );
2223}
2224
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002225#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002226
Paul Bakker5121ce52009-01-03 21:22:43 +00002227static const int small_prime[] =
2228{
2229 3, 5, 7, 11, 13, 17, 19, 23,
2230 29, 31, 37, 41, 43, 47, 53, 59,
2231 61, 67, 71, 73, 79, 83, 89, 97,
2232 101, 103, 107, 109, 113, 127, 131, 137,
2233 139, 149, 151, 157, 163, 167, 173, 179,
2234 181, 191, 193, 197, 199, 211, 223, 227,
2235 229, 233, 239, 241, 251, 257, 263, 269,
2236 271, 277, 281, 283, 293, 307, 311, 313,
2237 317, 331, 337, 347, 349, 353, 359, 367,
2238 373, 379, 383, 389, 397, 401, 409, 419,
2239 421, 431, 433, 439, 443, 449, 457, 461,
2240 463, 467, 479, 487, 491, 499, 503, 509,
2241 521, 523, 541, 547, 557, 563, 569, 571,
2242 577, 587, 593, 599, 601, 607, 613, 617,
2243 619, 631, 641, 643, 647, 653, 659, 661,
2244 673, 677, 683, 691, 701, 709, 719, 727,
2245 733, 739, 743, 751, 757, 761, 769, 773,
2246 787, 797, 809, 811, 821, 823, 827, 829,
2247 839, 853, 857, 859, 863, 877, 881, 883,
2248 887, 907, 911, 919, 929, 937, 941, 947,
2249 953, 967, 971, 977, 983, 991, 997, -103
2250};
2251
2252/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002253 * Small divisors test (X must be positive)
2254 *
2255 * Return values:
2256 * 0: no small factor (possible prime, more tests needed)
2257 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002258 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002259 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002261static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002262{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002263 int ret = 0;
2264 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002265 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002266
Paul Bakker5121ce52009-01-03 21:22:43 +00002267 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002268 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002269
2270 for( i = 0; small_prime[i] > 0; i++ )
2271 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002273 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002274
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002275 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002276
2277 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002278 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002279 }
2280
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002281cleanup:
2282 return( ret );
2283}
2284
2285/*
2286 * Miller-Rabin pseudo-primality test (HAC 4.24)
2287 */
Janos Follath72d555d2018-09-03 14:45:23 +01002288static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002289 int (*f_rng)(void *, unsigned char *, size_t),
2290 void *p_rng )
2291{
Pascal Junodb99183d2015-03-11 16:49:45 +01002292 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002293 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002294 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002295
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002296 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2297 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002298
Paul Bakker5121ce52009-01-03 21:22:43 +00002299 /*
2300 * W = |X| - 1
2301 * R = W >> lsb( W )
2302 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002303 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2304 s = mbedtls_mpi_lsb( &W );
2305 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2306 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002307
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002308 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002309
Janos Follath72d555d2018-09-03 14:45:23 +01002310 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002311 {
2312 /*
2313 * pick a random A, 1 < A < |X| - 1
2314 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002315 count = 0;
2316 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002317 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002318
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002319 j = mbedtls_mpi_bitlen( &A );
2320 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002321 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002322 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002323 }
2324
2325 if (count++ > 30) {
Jens Wiklanderb2aa9382019-01-17 13:30:57 +01002326 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2327 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002328 }
2329
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002330 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2331 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002332
2333 /*
2334 * A = A^R mod |X|
2335 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002336 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2339 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002340 continue;
2341
2342 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002343 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002344 {
2345 /*
2346 * A = A * A mod |X|
2347 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002348 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2349 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002350
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002351 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002352 break;
2353
2354 j++;
2355 }
2356
2357 /*
2358 * not prime if A != |X| - 1 or A == 1
2359 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002360 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2361 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002362 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002363 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002364 break;
2365 }
2366 }
2367
2368cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002369 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2370 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002371
2372 return( ret );
2373}
2374
2375/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002376 * Pseudo-primality test: small factors, then Miller-Rabin
2377 */
Darryl Green94759f62018-10-16 15:09:19 +01002378static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002379 int (*f_rng)(void *, unsigned char *, size_t),
2380 void *p_rng )
2381{
2382 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002384
2385 XX.s = 1;
2386 XX.n = X->n;
2387 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002389 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2390 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2391 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002393 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002394 return( 0 );
2395
2396 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2397 {
2398 if( ret == 1 )
2399 return( 0 );
2400
2401 return( ret );
2402 }
2403
Janos Follath72d555d2018-09-03 14:45:23 +01002404 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2405}
2406
2407/*
2408 * Pseudo-primality test, error probability 2^-80
2409 */
2410int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2411 int (*f_rng)(void *, unsigned char *, size_t),
2412 void *p_rng )
2413{
2414 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002415}
2416
2417/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002418 * Prime number generation
2419 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002420int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002421 int (*f_rng)(void *, unsigned char *, size_t),
2422 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002423{
Paul Bakker23986e52011-04-24 08:57:21 +00002424 int ret;
2425 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002426 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002427 mbedtls_mpi_uint r;
2428 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002429
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002430 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2431 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002432
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002433 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002434
2435 n = BITS_TO_LIMBS( nbits );
2436
Janos Follath72d555d2018-09-03 14:45:23 +01002437 /*
2438 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2439 */
2440 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2441 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2442 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2443
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002444 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002445
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002446 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002447 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002448
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002449 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002450
2451 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002452
2453 if( dh_flag == 0 )
2454 {
Janos Follath72d555d2018-09-03 14:45:23 +01002455 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002456 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002457 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002458 goto cleanup;
2459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002460 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002461 }
2462 }
2463 else
2464 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002465 /*
2466 * An necessary condition for Y and X = 2Y + 1 to be prime
2467 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2468 * Make sure it is satisfied, while keeping X = 3 mod 4
2469 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002470
2471 X->p[0] |= 2;
2472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002474 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002476 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002477 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002478
2479 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002480 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2481 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002482
2483 while( 1 )
2484 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002485 /*
2486 * First, check small factors for X and Y
2487 * before doing Miller-Rabin on any of them
2488 */
2489 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2490 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002491 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2492 == 0 &&
2493 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2494 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002495 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002496 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002497 }
2498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002499 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002500 goto cleanup;
2501
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002502 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002503 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002504 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2505 * so up Y by 6 and X by 12.
2506 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002507 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2508 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002509 }
2510 }
2511
2512cleanup:
2513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002514 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002515
2516 return( ret );
2517}
2518
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002519#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002520
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002521#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002522
Paul Bakker23986e52011-04-24 08:57:21 +00002523#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002524
2525static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2526{
2527 { 693, 609, 21 },
2528 { 1764, 868, 28 },
2529 { 768454923, 542167814, 1 }
2530};
2531
Paul Bakker5121ce52009-01-03 21:22:43 +00002532/*
2533 * Checkup routine
2534 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002535int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002536{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002537 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002538 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002539
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002540 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2541 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002543 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002544 "EFE021C2645FD1DC586E69184AF4A31E" \
2545 "D5F53E93B5F123FA41680867BA110131" \
2546 "944FE7952E2517337780CB0DB80E61AA" \
2547 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2548
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002549 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002550 "B2E7EFD37075B9F03FF989C7C5051C20" \
2551 "34D2A323810251127E7BF8625A4F49A5" \
2552 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2553 "5B5C25763222FEFCCFC38B832366C29E" ) );
2554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002555 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002556 "0066A198186C18C10B2F5ED9B522752A" \
2557 "9830B69916E535C8F047518A889A43A5" \
2558 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2559
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002560 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002561
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002563 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2564 "9E857EA95A03512E2BAE7391688D264A" \
2565 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2566 "8001B72E848A38CAE1C65F78E56ABDEF" \
2567 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2568 "ECF677152EF804370C1A305CAF3B5BF1" \
2569 "30879B56C61DE584A0F53A2447A51E" ) );
2570
2571 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002572 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002573
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002574 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002575 {
2576 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002577 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002578
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002579 ret = 1;
2580 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002581 }
2582
2583 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002584 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002585
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002586 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002587
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002588 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002589 "256567336059E52CAE22925474705F39A94" ) );
2590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002591 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002592 "6613F26162223DF488E9CD48CC132C7A" \
2593 "0AC93C701B001B092E4E5B9F73BCD27B" \
2594 "9EE50D0657C77F374E903CDFA4C642" ) );
2595
2596 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002597 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002598
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002599 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2600 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002601 {
2602 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002603 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002604
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002605 ret = 1;
2606 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002607 }
2608
2609 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002610 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002612 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002613
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002614 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002615 "36E139AEA55215609D2816998ED020BB" \
2616 "BD96C37890F65171D948E9BC7CBAA4D9" \
2617 "325D24D6A3C12710F10A09FA08AB87" ) );
2618
2619 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002620 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002622 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002623 {
2624 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002625 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002626
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002627 ret = 1;
2628 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002629 }
2630
2631 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002632 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002633
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002634 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002636 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002637 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2638 "C3DBA76456363A10869622EAC2DD84EC" \
2639 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2640
2641 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002642 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002643
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002644 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002645 {
2646 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002647 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002648
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002649 ret = 1;
2650 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002651 }
2652
2653 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002654 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002655
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002656 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002657 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002658
Paul Bakker66d5d072014-06-17 16:39:18 +02002659 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002660 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002661 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2662 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002663
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002664 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002665
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002666 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002667 {
2668 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002669 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002670
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002671 ret = 1;
2672 goto cleanup;
2673 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002674 }
2675
2676 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002677 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002678
Paul Bakker5121ce52009-01-03 21:22:43 +00002679cleanup:
2680
2681 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002682 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002684 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2685 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002686
2687 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002688 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002689
2690 return( ret );
2691}
2692
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002693#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002694
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002695#endif /* MBEDTLS_BIGNUM_C */