blob: ba4bb831fb8a4587c2e0fd6c70a9ac787c9b9600 [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
Chris Jones8b1f65e2020-11-25 15:12:39 +00001862 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
1863 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
1864 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1865
Paul Bakkerf6198c12012-05-16 08:02:29 +00001866 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001867 * Init temps and window size
1868 */
1869 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001870 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1871 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001872 memset( W, 0, sizeof( W ) );
1873
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001874 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001875
1876 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1877 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1878
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001879#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1881 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001882#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001883
Paul Bakker5121ce52009-01-03 21:22:43 +00001884 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001885 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1886 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1887 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001888
1889 /*
Paul Bakker50546922012-05-19 08:40:49 +00001890 * Compensate for negative A (and correct at the end)
1891 */
1892 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001893 if( neg )
1894 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001895 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001896 Apos.s = 1;
1897 A = &Apos;
1898 }
1899
1900 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001901 * If 1st call, pre-compute R^2 mod N
1902 */
1903 if( _RR == NULL || _RR->p == NULL )
1904 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001905 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1906 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1907 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001908
1909 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001910 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001911 }
1912 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001913 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001914
1915 /*
1916 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1917 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001918 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1919 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001920 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001921 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001922
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001923 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001924
1925 /*
1926 * X = R^2 * R^-1 mod N = R mod N
1927 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001928 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001929 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001930
1931 if( wsize > 1 )
1932 {
1933 /*
1934 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1935 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001936 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001937
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001938 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1939 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001940
1941 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001942 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001943
Paul Bakker5121ce52009-01-03 21:22:43 +00001944 /*
1945 * W[i] = W[i - 1] * W[1]
1946 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001947 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001948 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001949 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1950 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001951
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001952 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001953 }
1954 }
1955
1956 nblimbs = E->n;
1957 bufsize = 0;
1958 nbits = 0;
1959 wbits = 0;
1960 state = 0;
1961
1962 while( 1 )
1963 {
1964 if( bufsize == 0 )
1965 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001966 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001967 break;
1968
Paul Bakker0d7702c2013-10-29 16:18:35 +01001969 nblimbs--;
1970
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001971 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001972 }
1973
1974 bufsize--;
1975
1976 ei = (E->p[nblimbs] >> bufsize) & 1;
1977
1978 /*
1979 * skip leading 0s
1980 */
1981 if( ei == 0 && state == 0 )
1982 continue;
1983
1984 if( ei == 0 && state == 1 )
1985 {
1986 /*
1987 * out of window, square X
1988 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001989 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001990 continue;
1991 }
1992
1993 /*
1994 * add ei to current window
1995 */
1996 state = 2;
1997
1998 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001999 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002000
2001 if( nbits == wsize )
2002 {
2003 /*
2004 * X = X^wsize R^-1 mod N
2005 */
2006 for( i = 0; i < wsize; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002007 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002008
2009 /*
2010 * X = X * W[wbits] R^-1 mod N
2011 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002012 mpi_montmul( X, &W[wbits], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002013
2014 state--;
2015 nbits = 0;
2016 wbits = 0;
2017 }
2018 }
2019
2020 /*
2021 * process the remaining bits
2022 */
2023 for( i = 0; i < nbits; i++ )
2024 {
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002025 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002026
2027 wbits <<= 1;
2028
Paul Bakker66d5d072014-06-17 16:39:18 +02002029 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002030 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002031 }
2032
2033 /*
2034 * X = A^E * R * R^-1 mod N = A^E mod N
2035 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002036 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002037
Hanno Beckera4af1c42017-04-18 09:07:45 +01002038 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002039 {
2040 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002041 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002042 }
2043
Paul Bakker5121ce52009-01-03 21:22:43 +00002044cleanup:
2045
Paul Bakker66d5d072014-06-17 16:39:18 +02002046 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002047 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002048
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002050
Paul Bakker75a28602014-03-31 12:08:17 +02002051 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002053
2054 return( ret );
2055}
2056
Paul Bakker5121ce52009-01-03 21:22:43 +00002057/*
2058 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2059 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002061{
Paul Bakker23986e52011-04-24 08:57:21 +00002062 int ret;
2063 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002064 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002065
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002066 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002067
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002068 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2069 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002070
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002071 lz = mbedtls_mpi_lsb( &TA );
2072 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002073
Paul Bakker66d5d072014-06-17 16:39:18 +02002074 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002075 lz = lzt;
2076
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002077 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2078 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002079
Paul Bakker5121ce52009-01-03 21:22:43 +00002080 TA.s = TB.s = 1;
2081
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002082 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002083 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002084 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2085 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002086
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002087 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002088 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002089 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2090 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002091 }
2092 else
2093 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002094 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2095 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002096 }
2097 }
2098
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002099 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2100 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002101
2102cleanup:
2103
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002104 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002105
2106 return( ret );
2107}
2108
Paul Bakker33dc46b2014-04-30 16:11:39 +02002109/*
2110 * Fill X with size bytes of random.
2111 *
2112 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002113 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002114 * deterministic, eg for tests).
2115 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002116int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002117 int (*f_rng)(void *, unsigned char *, size_t),
2118 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002119{
Paul Bakker23986e52011-04-24 08:57:21 +00002120 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002121 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02002122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002123 if( size > MBEDTLS_MPI_MAX_SIZE )
2124 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002125
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002126 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2127 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002128
2129cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01002130 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002131 return( ret );
2132}
2133
Paul Bakker5121ce52009-01-03 21:22:43 +00002134/*
2135 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2136 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002137int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002138{
2139 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002140 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002141
Hanno Becker4bcb4912017-04-18 15:49:39 +01002142 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002143 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2146 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2147 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002148
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002149 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002150
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002151 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002152 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002153 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002154 goto cleanup;
2155 }
2156
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002157 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2158 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2159 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2160 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002161
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002162 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2163 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2164 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2165 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002166
2167 do
2168 {
2169 while( ( TU.p[0] & 1 ) == 0 )
2170 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002171 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002172
2173 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2174 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002175 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2176 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002177 }
2178
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002179 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2180 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002181 }
2182
2183 while( ( TV.p[0] & 1 ) == 0 )
2184 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002185 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002186
2187 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2188 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002189 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2190 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002191 }
2192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002193 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2194 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002195 }
2196
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002197 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002198 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002199 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2200 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2201 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002202 }
2203 else
2204 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002205 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2206 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2207 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002208 }
2209 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002210 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002211
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002212 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2213 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002215 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2216 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002218 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002219
2220cleanup:
2221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002222 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2223 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2224 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002225
2226 return( ret );
2227}
2228
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002229#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002230
Paul Bakker5121ce52009-01-03 21:22:43 +00002231static const int small_prime[] =
2232{
2233 3, 5, 7, 11, 13, 17, 19, 23,
2234 29, 31, 37, 41, 43, 47, 53, 59,
2235 61, 67, 71, 73, 79, 83, 89, 97,
2236 101, 103, 107, 109, 113, 127, 131, 137,
2237 139, 149, 151, 157, 163, 167, 173, 179,
2238 181, 191, 193, 197, 199, 211, 223, 227,
2239 229, 233, 239, 241, 251, 257, 263, 269,
2240 271, 277, 281, 283, 293, 307, 311, 313,
2241 317, 331, 337, 347, 349, 353, 359, 367,
2242 373, 379, 383, 389, 397, 401, 409, 419,
2243 421, 431, 433, 439, 443, 449, 457, 461,
2244 463, 467, 479, 487, 491, 499, 503, 509,
2245 521, 523, 541, 547, 557, 563, 569, 571,
2246 577, 587, 593, 599, 601, 607, 613, 617,
2247 619, 631, 641, 643, 647, 653, 659, 661,
2248 673, 677, 683, 691, 701, 709, 719, 727,
2249 733, 739, 743, 751, 757, 761, 769, 773,
2250 787, 797, 809, 811, 821, 823, 827, 829,
2251 839, 853, 857, 859, 863, 877, 881, 883,
2252 887, 907, 911, 919, 929, 937, 941, 947,
2253 953, 967, 971, 977, 983, 991, 997, -103
2254};
2255
2256/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002257 * Small divisors test (X must be positive)
2258 *
2259 * Return values:
2260 * 0: no small factor (possible prime, more tests needed)
2261 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002262 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002263 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002264 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002265static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002266{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002267 int ret = 0;
2268 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002269 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002270
Paul Bakker5121ce52009-01-03 21:22:43 +00002271 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002273
2274 for( i = 0; small_prime[i] > 0; i++ )
2275 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002276 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002277 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002278
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002279 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002280
2281 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002282 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002283 }
2284
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002285cleanup:
2286 return( ret );
2287}
2288
2289/*
2290 * Miller-Rabin pseudo-primality test (HAC 4.24)
2291 */
Janos Follath72d555d2018-09-03 14:45:23 +01002292static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002293 int (*f_rng)(void *, unsigned char *, size_t),
2294 void *p_rng )
2295{
Pascal Junodb99183d2015-03-11 16:49:45 +01002296 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002297 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002298 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002299
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002300 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2301 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002302
Paul Bakker5121ce52009-01-03 21:22:43 +00002303 /*
2304 * W = |X| - 1
2305 * R = W >> lsb( W )
2306 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2308 s = mbedtls_mpi_lsb( &W );
2309 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2310 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002311
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002312 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002313
Janos Follath72d555d2018-09-03 14:45:23 +01002314 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002315 {
2316 /*
2317 * pick a random A, 1 < A < |X| - 1
2318 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002319 count = 0;
2320 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002321 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002322
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002323 j = mbedtls_mpi_bitlen( &A );
2324 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002325 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002326 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002327 }
2328
2329 if (count++ > 30) {
Jens Wiklanderb2aa9382019-01-17 13:30:57 +01002330 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2331 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002332 }
2333
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002334 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2335 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002336
2337 /*
2338 * A = A^R mod |X|
2339 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002340 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2343 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002344 continue;
2345
2346 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002348 {
2349 /*
2350 * A = A * A mod |X|
2351 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002352 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2353 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002354
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002355 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002356 break;
2357
2358 j++;
2359 }
2360
2361 /*
2362 * not prime if A != |X| - 1 or A == 1
2363 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002364 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2365 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002366 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002368 break;
2369 }
2370 }
2371
2372cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002373 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2374 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002375
2376 return( ret );
2377}
2378
2379/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002380 * Pseudo-primality test: small factors, then Miller-Rabin
2381 */
Darryl Green94759f62018-10-16 15:09:19 +01002382static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002383 int (*f_rng)(void *, unsigned char *, size_t),
2384 void *p_rng )
2385{
2386 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002387 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002388
2389 XX.s = 1;
2390 XX.n = X->n;
2391 XX.p = X->p;
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, 0 ) == 0 ||
2394 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2395 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002397 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002398 return( 0 );
2399
2400 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2401 {
2402 if( ret == 1 )
2403 return( 0 );
2404
2405 return( ret );
2406 }
2407
Janos Follath72d555d2018-09-03 14:45:23 +01002408 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2409}
2410
2411/*
2412 * Pseudo-primality test, error probability 2^-80
2413 */
2414int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2415 int (*f_rng)(void *, unsigned char *, size_t),
2416 void *p_rng )
2417{
2418 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002419}
2420
2421/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002422 * Prime number generation
2423 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002424int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002425 int (*f_rng)(void *, unsigned char *, size_t),
2426 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002427{
Paul Bakker23986e52011-04-24 08:57:21 +00002428 int ret;
2429 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002430 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002431 mbedtls_mpi_uint r;
2432 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2435 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002436
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002437 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002438
2439 n = BITS_TO_LIMBS( nbits );
2440
Janos Follath72d555d2018-09-03 14:45:23 +01002441 /*
2442 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2443 */
2444 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2445 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2446 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2447
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002448 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002449
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002450 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002451 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002452
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002453 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002454
2455 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002456
2457 if( dh_flag == 0 )
2458 {
Janos Follath72d555d2018-09-03 14:45:23 +01002459 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002460 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002461 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002462 goto cleanup;
2463
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002464 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002465 }
2466 }
2467 else
2468 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002469 /*
2470 * An necessary condition for Y and X = 2Y + 1 to be prime
2471 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2472 * Make sure it is satisfied, while keeping X = 3 mod 4
2473 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002474
2475 X->p[0] |= 2;
2476
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002477 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002478 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002479 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002480 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002481 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002482
2483 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002484 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2485 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002486
2487 while( 1 )
2488 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002489 /*
2490 * First, check small factors for X and Y
2491 * before doing Miller-Rabin on any of them
2492 */
2493 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2494 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002495 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2496 == 0 &&
2497 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2498 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002499 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002500 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002501 }
2502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002503 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002504 goto cleanup;
2505
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002506 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002507 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002508 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2509 * so up Y by 6 and X by 12.
2510 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002511 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2512 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002513 }
2514 }
2515
2516cleanup:
2517
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002518 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002519
2520 return( ret );
2521}
2522
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002523#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002525#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002526
Paul Bakker23986e52011-04-24 08:57:21 +00002527#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002528
2529static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2530{
2531 { 693, 609, 21 },
2532 { 1764, 868, 28 },
2533 { 768454923, 542167814, 1 }
2534};
2535
Paul Bakker5121ce52009-01-03 21:22:43 +00002536/*
2537 * Checkup routine
2538 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002539int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002540{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002541 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002542 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002543
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002544 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2545 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002546
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002547 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002548 "EFE021C2645FD1DC586E69184AF4A31E" \
2549 "D5F53E93B5F123FA41680867BA110131" \
2550 "944FE7952E2517337780CB0DB80E61AA" \
2551 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2552
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002553 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002554 "B2E7EFD37075B9F03FF989C7C5051C20" \
2555 "34D2A323810251127E7BF8625A4F49A5" \
2556 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2557 "5B5C25763222FEFCCFC38B832366C29E" ) );
2558
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002559 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002560 "0066A198186C18C10B2F5ED9B522752A" \
2561 "9830B69916E535C8F047518A889A43A5" \
2562 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2563
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002564 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002565
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002566 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002567 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2568 "9E857EA95A03512E2BAE7391688D264A" \
2569 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2570 "8001B72E848A38CAE1C65F78E56ABDEF" \
2571 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2572 "ECF677152EF804370C1A305CAF3B5BF1" \
2573 "30879B56C61DE584A0F53A2447A51E" ) );
2574
2575 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002576 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002578 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002579 {
2580 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002581 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002582
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002583 ret = 1;
2584 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002585 }
2586
2587 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002588 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002589
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002590 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002591
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002592 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002593 "256567336059E52CAE22925474705F39A94" ) );
2594
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002595 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002596 "6613F26162223DF488E9CD48CC132C7A" \
2597 "0AC93C701B001B092E4E5B9F73BCD27B" \
2598 "9EE50D0657C77F374E903CDFA4C642" ) );
2599
2600 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002601 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002602
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002603 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2604 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002605 {
2606 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002607 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002608
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002609 ret = 1;
2610 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002611 }
2612
2613 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002614 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002615
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002616 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002617
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002618 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002619 "36E139AEA55215609D2816998ED020BB" \
2620 "BD96C37890F65171D948E9BC7CBAA4D9" \
2621 "325D24D6A3C12710F10A09FA08AB87" ) );
2622
2623 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002624 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002625
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002626 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002627 {
2628 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002629 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002630
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002631 ret = 1;
2632 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002633 }
2634
2635 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002636 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002637
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002638 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002639
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002640 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002641 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2642 "C3DBA76456363A10869622EAC2DD84EC" \
2643 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2644
2645 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002646 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002647
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002648 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002649 {
2650 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002651 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002652
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002653 ret = 1;
2654 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002655 }
2656
2657 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002658 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002659
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002660 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002661 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002662
Paul Bakker66d5d072014-06-17 16:39:18 +02002663 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002664 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002665 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2666 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002667
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002668 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002669
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002670 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002671 {
2672 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002673 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002674
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002675 ret = 1;
2676 goto cleanup;
2677 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002678 }
2679
2680 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002681 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002682
Paul Bakker5121ce52009-01-03 21:22:43 +00002683cleanup:
2684
2685 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002686 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002687
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002688 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2689 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002690
2691 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002692 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002693
2694 return( ret );
2695}
2696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002697#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002698
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002699#endif /* MBEDTLS_BIGNUM_C */