blob: 3ed2a12173c9da5cb45aeea75e66163df36928b8 [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 )
Gilles Peskine91070e42020-07-23 01:16:46 +02001204 {
1205 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1206 goto cleanup;
1207 }
Gilles Peskinefa85cc22020-06-08 22:50:35 +02001208 --X->p[n];
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001209 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001210
1211cleanup:
1212
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001213 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001214
1215 return( ret );
1216}
1217
1218/*
1219 * Signed addition: X = A + B
1220 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001221int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001222{
1223 int ret, s = A->s;
1224
1225 if( A->s * B->s < 0 )
1226 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001227 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001228 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001229 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001230 X->s = s;
1231 }
1232 else
1233 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001234 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001235 X->s = -s;
1236 }
1237 }
1238 else
1239 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001240 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001241 X->s = s;
1242 }
1243
1244cleanup:
1245
1246 return( ret );
1247}
1248
1249/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001250 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001251 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001252int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001253{
1254 int ret, s = A->s;
1255
1256 if( A->s * B->s > 0 )
1257 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001258 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001259 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001260 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001261 X->s = s;
1262 }
1263 else
1264 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001265 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001266 X->s = -s;
1267 }
1268 }
1269 else
1270 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001271 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001272 X->s = s;
1273 }
1274
1275cleanup:
1276
1277 return( ret );
1278}
1279
1280/*
1281 * Signed addition: X = A + b
1282 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001283int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001284{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001285 mbedtls_mpi _B;
1286 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001287
1288 p[0] = ( b < 0 ) ? -b : b;
1289 _B.s = ( b < 0 ) ? -1 : 1;
1290 _B.n = 1;
1291 _B.p = p;
1292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001293 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001294}
1295
1296/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001297 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001298 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001299int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001300{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001301 mbedtls_mpi _B;
1302 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001303
1304 p[0] = ( b < 0 ) ? -b : b;
1305 _B.s = ( b < 0 ) ? -1 : 1;
1306 _B.n = 1;
1307 _B.p = p;
1308
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001309 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001310}
1311
1312/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001313 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001314 */
1315static
1316#if defined(__APPLE__) && defined(__arm__)
1317/*
1318 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1319 * appears to need this to prevent bad ARM code generation at -O3.
1320 */
1321__attribute__ ((noinline))
1322#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001323void 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 +00001324{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001325 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001326
1327#if defined(MULADDC_HUIT)
1328 for( ; i >= 8; i -= 8 )
1329 {
1330 MULADDC_INIT
1331 MULADDC_HUIT
1332 MULADDC_STOP
1333 }
1334
1335 for( ; i > 0; i-- )
1336 {
1337 MULADDC_INIT
1338 MULADDC_CORE
1339 MULADDC_STOP
1340 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001341#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001342 for( ; i >= 16; i -= 16 )
1343 {
1344 MULADDC_INIT
1345 MULADDC_CORE MULADDC_CORE
1346 MULADDC_CORE MULADDC_CORE
1347 MULADDC_CORE MULADDC_CORE
1348 MULADDC_CORE MULADDC_CORE
1349
1350 MULADDC_CORE MULADDC_CORE
1351 MULADDC_CORE MULADDC_CORE
1352 MULADDC_CORE MULADDC_CORE
1353 MULADDC_CORE MULADDC_CORE
1354 MULADDC_STOP
1355 }
1356
1357 for( ; i >= 8; i -= 8 )
1358 {
1359 MULADDC_INIT
1360 MULADDC_CORE MULADDC_CORE
1361 MULADDC_CORE MULADDC_CORE
1362
1363 MULADDC_CORE MULADDC_CORE
1364 MULADDC_CORE MULADDC_CORE
1365 MULADDC_STOP
1366 }
1367
1368 for( ; i > 0; i-- )
1369 {
1370 MULADDC_INIT
1371 MULADDC_CORE
1372 MULADDC_STOP
1373 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001374#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001375
1376 t++;
1377
1378 do {
1379 *d += c; c = ( *d < c ); d++;
1380 }
1381 while( c != 0 );
1382}
1383
1384/*
1385 * Baseline multiplication: X = A * B (HAC 14.12)
1386 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001387int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001388{
Paul Bakker23986e52011-04-24 08:57:21 +00001389 int ret;
1390 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001393 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001394
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001395 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1396 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001397
Paul Bakker23986e52011-04-24 08:57:21 +00001398 for( i = A->n; i > 0; i-- )
1399 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001400 break;
1401
Paul Bakker23986e52011-04-24 08:57:21 +00001402 for( j = B->n; j > 0; j-- )
1403 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001404 break;
1405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1407 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001408
Paul Bakker23986e52011-04-24 08:57:21 +00001409 for( i++; j > 0; j-- )
1410 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001411
1412 X->s = A->s * B->s;
1413
1414cleanup:
1415
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001416 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001417
1418 return( ret );
1419}
1420
1421/*
1422 * Baseline multiplication: X = A * b
1423 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001424int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001425{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001426 mbedtls_mpi _B;
1427 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001428
1429 _B.s = 1;
1430 _B.n = 1;
1431 _B.p = p;
1432 p[0] = b;
1433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001434 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001435}
1436
1437/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001438 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1439 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001440 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001441static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1442 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001443{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001444#if defined(MBEDTLS_HAVE_UDBL)
1445 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001446#else
Simon Butcher9803d072016-01-03 00:24:34 +00001447 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1448 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001449 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1450 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001451 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001452#endif
1453
Simon Butcher15b15d12015-11-26 19:35:03 +00001454 /*
1455 * Check for overflow
1456 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001457 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001458 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001459 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001460
Simon Butcherf5ba0452015-12-27 23:01:55 +00001461 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001462 }
1463
1464#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001465 dividend = (mbedtls_t_udbl) u1 << biL;
1466 dividend |= (mbedtls_t_udbl) u0;
1467 quotient = dividend / d;
1468 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1469 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1470
1471 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001472 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001473
1474 return (mbedtls_mpi_uint) quotient;
1475#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001476
1477 /*
1478 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1479 * Vol. 2 - Seminumerical Algorithms, Knuth
1480 */
1481
1482 /*
1483 * Normalize the divisor, d, and dividend, u0, u1
1484 */
1485 s = mbedtls_clz( d );
1486 d = d << s;
1487
1488 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001489 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001490 u0 = u0 << s;
1491
1492 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001493 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001494
1495 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001496 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001497
1498 /*
1499 * Find the first quotient and remainder
1500 */
1501 q1 = u1 / d1;
1502 r0 = u1 - d1 * q1;
1503
1504 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1505 {
1506 q1 -= 1;
1507 r0 += d1;
1508
1509 if ( r0 >= radix ) break;
1510 }
1511
Simon Butcherf5ba0452015-12-27 23:01:55 +00001512 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001513 q0 = rAX / d1;
1514 r0 = rAX - q0 * d1;
1515
1516 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1517 {
1518 q0 -= 1;
1519 r0 += d1;
1520
1521 if ( r0 >= radix ) break;
1522 }
1523
1524 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001525 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001526
1527 quotient = q1 * radix + q0;
1528
1529 return quotient;
1530#endif
1531}
1532
1533/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001534 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001535 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001536int 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 +00001537{
Paul Bakker23986e52011-04-24 08:57:21 +00001538 int ret;
1539 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001540 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001541
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001542 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1543 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001544
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001545 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1546 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001547
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001548 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001549 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001550 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1551 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001552 return( 0 );
1553 }
1554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001555 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1556 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001557 X.s = Y.s = 1;
1558
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001559 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1560 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1561 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1562 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001563
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001564 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001565 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001566 {
1567 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001568 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1569 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001570 }
1571 else k = 0;
1572
1573 n = X.n - 1;
1574 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001575 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001576
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001577 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001578 {
1579 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001580 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001581 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001582 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001583
1584 for( i = n; i > t ; i-- )
1585 {
1586 if( X.p[i] >= Y.p[t] )
1587 Z.p[i - t - 1] = ~0;
1588 else
1589 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001590 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1591 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001592 }
1593
1594 Z.p[i - t - 1]++;
1595 do
1596 {
1597 Z.p[i - t - 1]--;
1598
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001599 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001600 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001601 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001602 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001603
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001604 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001605 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1606 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001607 T2.p[2] = X.p[i];
1608 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001609 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001610
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001611 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1612 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1613 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001615 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001616 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001617 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1618 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1619 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001620 Z.p[i - t - 1]--;
1621 }
1622 }
1623
1624 if( Q != NULL )
1625 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001626 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001627 Q->s = A->s * B->s;
1628 }
1629
1630 if( R != NULL )
1631 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001632 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001633 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001634 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001637 R->s = 1;
1638 }
1639
1640cleanup:
1641
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001642 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1643 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001644
1645 return( ret );
1646}
1647
1648/*
1649 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001650 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651int 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 +00001652{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001653 mbedtls_mpi _B;
1654 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001655
1656 p[0] = ( b < 0 ) ? -b : b;
1657 _B.s = ( b < 0 ) ? -1 : 1;
1658 _B.n = 1;
1659 _B.p = p;
1660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001662}
1663
1664/*
1665 * Modulo: R = A mod B
1666 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001667int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001668{
1669 int ret;
1670
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1672 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001673
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001674 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001676 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1677 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001678
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001679 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1680 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001681
1682cleanup:
1683
1684 return( ret );
1685}
1686
1687/*
1688 * Modulo: r = A mod b
1689 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001690int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001691{
Paul Bakker23986e52011-04-24 08:57:21 +00001692 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001693 mbedtls_mpi_uint x, y, z;
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_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001697
1698 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001699 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001700
1701 /*
1702 * handle trivial cases
1703 */
1704 if( b == 1 )
1705 {
1706 *r = 0;
1707 return( 0 );
1708 }
1709
1710 if( b == 2 )
1711 {
1712 *r = A->p[0] & 1;
1713 return( 0 );
1714 }
1715
1716 /*
1717 * general case
1718 */
Paul Bakker23986e52011-04-24 08:57:21 +00001719 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001720 {
Paul Bakker23986e52011-04-24 08:57:21 +00001721 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001722 y = ( y << biH ) | ( x >> biH );
1723 z = y / b;
1724 y -= z * b;
1725
1726 x <<= biH;
1727 y = ( y << biH ) | ( x >> biH );
1728 z = y / b;
1729 y -= z * b;
1730 }
1731
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001732 /*
1733 * If A is negative, then the current y represents a negative value.
1734 * Flipping it to the positive side.
1735 */
1736 if( A->s < 0 && y != 0 )
1737 y = b - y;
1738
Paul Bakker5121ce52009-01-03 21:22:43 +00001739 *r = y;
1740
1741 return( 0 );
1742}
1743
1744/*
1745 * Fast Montgomery initialization (thanks to Tom St Denis)
1746 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001747static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001748{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001749 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001750 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001751
1752 x = m0;
1753 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001754
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001755 for( i = biL; i >= 8; i /= 2 )
1756 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001757
1758 *mm = ~x + 1;
1759}
1760
Gilles Peskined108d072020-06-04 15:00:49 +02001761/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1762 *
1763 * \param[in,out] A One of the numbers to multiply.
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001764 * It must have at least as many limbs as N
1765 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskined108d072020-06-04 15:00:49 +02001766 * On successful completion, A contains the result of
1767 * the multiplication A * B * R^-1 mod N where
1768 * R = (2^ciL)^n.
1769 * \param[in] B One of the numbers to multiply.
1770 * It must be nonzero and must not have more limbs than N
1771 * (B->n <= N->n).
1772 * \param[in] N The modulo. N must be odd.
1773 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1774 * This is -N^-1 mod 2^ciL.
1775 * \param[in,out] T A bignum for temporary storage.
1776 * It must be at least twice the limb size of N plus 2
1777 * (T->n >= 2 * (N->n + 1)).
1778 * Its initial content is unused and
1779 * its final content is indeterminate.
1780 * Note that unlike the usual convention in the library
1781 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00001782 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001783static 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 +02001784 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001785{
Paul Bakker23986e52011-04-24 08:57:21 +00001786 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001787 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001788
1789 memset( T->p, 0, T->n * ciL );
1790
1791 d = T->p;
1792 n = N->n;
1793 m = ( B->n < n ) ? B->n : n;
1794
1795 for( i = 0; i < n; i++ )
1796 {
1797 /*
1798 * T = (T + u0*B + u1*N) / 2^biL
1799 */
1800 u0 = A->p[i];
1801 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1802
1803 mpi_mul_hlp( m, B->p, d, u0 );
1804 mpi_mul_hlp( n, N->p, d, u1 );
1805
1806 *d++ = u0; d[n + 1] = 0;
1807 }
1808
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001809 /* At this point, d is either the desired result or the desired result
1810 * plus N. We now potentially subtract N, avoiding leaking whether the
1811 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001812
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001813 /* Copy the n least significant limbs of d to A, so that
1814 * A = d if d < N (recall that N has n limbs). */
1815 memcpy( A->p, d, n * ciL );
Gilles Peskinef3317e62020-06-09 10:39:38 +02001816 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001817 * do the calculation without using conditional tests. */
1818 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine7ff812e2020-06-04 21:05:24 +02001819 d[n] += 1;
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001820 d[n] -= mpi_sub_hlp( n, d, N->p );
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001821 /* If d0 < N then d < (2^biL)^n
1822 * so d[n] == 0 and we want to keep A as it is.
1823 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
1824 * so d[n] == 1 and we want to set A to the result of the subtraction
1825 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
1826 * This exactly corresponds to a conditional assignment. */
1827 mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001828}
1829
1830/*
1831 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskined108d072020-06-04 15:00:49 +02001832 *
1833 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001834 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001835static 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 +00001836{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001837 mbedtls_mpi_uint z = 1;
1838 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001839
Paul Bakker8ddb6452013-02-27 14:56:33 +01001840 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001841 U.p = &z;
1842
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001843 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001844}
1845
1846/*
1847 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1848 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001849int 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 +00001850{
Paul Bakker23986e52011-04-24 08:57:21 +00001851 int ret;
1852 size_t wbits, wsize, one = 1;
1853 size_t i, j, nblimbs;
1854 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001855 mbedtls_mpi_uint ei, mm, state;
Daniel Otte19394602020-08-21 12:34:29 +02001856 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001857 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001858
Hanno Becker930ec7d2018-03-09 10:48:00 +00001859 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001860 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001861
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001862 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1863 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001864
Chris Jones8b1f65e2020-11-25 15:12:39 +00001865 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
1866 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
1867 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1868
Paul Bakkerf6198c12012-05-16 08:02:29 +00001869 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001870 * Init temps and window size
1871 */
1872 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001873 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1874 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001875 memset( W, 0, sizeof( W ) );
1876
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001877 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001878
1879 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1880 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1881
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001882#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001883 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1884 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001885#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001886
Paul Bakker5121ce52009-01-03 21:22:43 +00001887 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001888 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1889 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1890 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001891
1892 /*
Paul Bakker50546922012-05-19 08:40:49 +00001893 * Compensate for negative A (and correct at the end)
1894 */
1895 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001896 if( neg )
1897 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001898 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001899 Apos.s = 1;
1900 A = &Apos;
1901 }
1902
1903 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001904 * If 1st call, pre-compute R^2 mod N
1905 */
1906 if( _RR == NULL || _RR->p == NULL )
1907 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001908 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1909 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1910 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001911
1912 if( _RR != NULL )
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 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001916 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001917
1918 /*
1919 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1920 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001921 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1922 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001923 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001924 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001925
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001926 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001927
1928 /*
1929 * X = R^2 * R^-1 mod N = R mod N
1930 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001931 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001932 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001933
1934 if( wsize > 1 )
1935 {
1936 /*
1937 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1938 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001939 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001940
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001941 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1942 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001943
1944 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001945 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001946
Paul Bakker5121ce52009-01-03 21:22:43 +00001947 /*
1948 * W[i] = W[i - 1] * W[1]
1949 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001950 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001951 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001952 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1953 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001954
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001955 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956 }
1957 }
1958
1959 nblimbs = E->n;
1960 bufsize = 0;
1961 nbits = 0;
1962 wbits = 0;
1963 state = 0;
1964
1965 while( 1 )
1966 {
1967 if( bufsize == 0 )
1968 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001969 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001970 break;
1971
Paul Bakker0d7702c2013-10-29 16:18:35 +01001972 nblimbs--;
1973
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001974 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001975 }
1976
1977 bufsize--;
1978
1979 ei = (E->p[nblimbs] >> bufsize) & 1;
1980
1981 /*
1982 * skip leading 0s
1983 */
1984 if( ei == 0 && state == 0 )
1985 continue;
1986
1987 if( ei == 0 && state == 1 )
1988 {
1989 /*
1990 * out of window, square X
1991 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001992 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001993 continue;
1994 }
1995
1996 /*
1997 * add ei to current window
1998 */
1999 state = 2;
2000
2001 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002002 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002003
2004 if( nbits == wsize )
2005 {
2006 /*
2007 * X = X^wsize R^-1 mod N
2008 */
2009 for( i = 0; i < wsize; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002010 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002011
2012 /*
2013 * X = X * W[wbits] R^-1 mod N
2014 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002015 mpi_montmul( X, &W[wbits], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002016
2017 state--;
2018 nbits = 0;
2019 wbits = 0;
2020 }
2021 }
2022
2023 /*
2024 * process the remaining bits
2025 */
2026 for( i = 0; i < nbits; i++ )
2027 {
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002028 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002029
2030 wbits <<= 1;
2031
Paul Bakker66d5d072014-06-17 16:39:18 +02002032 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002033 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002034 }
2035
2036 /*
2037 * X = A^E * R * R^-1 mod N = A^E mod N
2038 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002039 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002040
Hanno Beckera4af1c42017-04-18 09:07:45 +01002041 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002042 {
2043 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002044 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002045 }
2046
Paul Bakker5121ce52009-01-03 21:22:43 +00002047cleanup:
2048
Paul Bakker66d5d072014-06-17 16:39:18 +02002049 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002050 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002051
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002053
Paul Bakker75a28602014-03-31 12:08:17 +02002054 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002055 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002056
2057 return( ret );
2058}
2059
Paul Bakker5121ce52009-01-03 21:22:43 +00002060/*
2061 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2062 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002063int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002064{
Paul Bakker23986e52011-04-24 08:57:21 +00002065 int ret;
2066 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002067 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002068
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002069 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002070
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002071 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2072 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002073
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002074 lz = mbedtls_mpi_lsb( &TA );
2075 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002076
Paul Bakker66d5d072014-06-17 16:39:18 +02002077 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002078 lz = lzt;
2079
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002080 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2081 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002082
Paul Bakker5121ce52009-01-03 21:22:43 +00002083 TA.s = TB.s = 1;
2084
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002085 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002086 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002087 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2088 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002089
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002090 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002091 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002092 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2093 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002094 }
2095 else
2096 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002097 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2098 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002099 }
2100 }
2101
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002102 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2103 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002104
2105cleanup:
2106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002107 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002108
2109 return( ret );
2110}
2111
Paul Bakker33dc46b2014-04-30 16:11:39 +02002112/*
2113 * Fill X with size bytes of random.
2114 *
2115 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002116 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002117 * deterministic, eg for tests).
2118 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002119int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002120 int (*f_rng)(void *, unsigned char *, size_t),
2121 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002122{
Paul Bakker23986e52011-04-24 08:57:21 +00002123 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002124 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02002125
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002126 if( size > MBEDTLS_MPI_MAX_SIZE )
2127 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002129 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2130 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002131
2132cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01002133 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002134 return( ret );
2135}
2136
Paul Bakker5121ce52009-01-03 21:22:43 +00002137/*
2138 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2139 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002140int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002141{
2142 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002143 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002144
Hanno Becker4bcb4912017-04-18 15:49:39 +01002145 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002146 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002147
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002148 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2149 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2150 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002152 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002153
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002154 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002155 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002156 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002157 goto cleanup;
2158 }
2159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2161 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2162 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2163 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002164
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002165 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2166 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2167 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2168 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002169
2170 do
2171 {
2172 while( ( TU.p[0] & 1 ) == 0 )
2173 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002174 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002175
2176 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2177 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002178 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2179 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002180 }
2181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002182 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2183 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002184 }
2185
2186 while( ( TV.p[0] & 1 ) == 0 )
2187 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002189
2190 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2191 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002192 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2193 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002194 }
2195
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002196 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2197 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002198 }
2199
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002200 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002201 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002202 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2203 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2204 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002205 }
2206 else
2207 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002208 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2209 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2210 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002211 }
2212 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002213 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002215 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2216 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002218 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2219 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002220
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002221 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002222
2223cleanup:
2224
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002225 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2226 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2227 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002228
2229 return( ret );
2230}
2231
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002232#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002233
Paul Bakker5121ce52009-01-03 21:22:43 +00002234static const int small_prime[] =
2235{
2236 3, 5, 7, 11, 13, 17, 19, 23,
2237 29, 31, 37, 41, 43, 47, 53, 59,
2238 61, 67, 71, 73, 79, 83, 89, 97,
2239 101, 103, 107, 109, 113, 127, 131, 137,
2240 139, 149, 151, 157, 163, 167, 173, 179,
2241 181, 191, 193, 197, 199, 211, 223, 227,
2242 229, 233, 239, 241, 251, 257, 263, 269,
2243 271, 277, 281, 283, 293, 307, 311, 313,
2244 317, 331, 337, 347, 349, 353, 359, 367,
2245 373, 379, 383, 389, 397, 401, 409, 419,
2246 421, 431, 433, 439, 443, 449, 457, 461,
2247 463, 467, 479, 487, 491, 499, 503, 509,
2248 521, 523, 541, 547, 557, 563, 569, 571,
2249 577, 587, 593, 599, 601, 607, 613, 617,
2250 619, 631, 641, 643, 647, 653, 659, 661,
2251 673, 677, 683, 691, 701, 709, 719, 727,
2252 733, 739, 743, 751, 757, 761, 769, 773,
2253 787, 797, 809, 811, 821, 823, 827, 829,
2254 839, 853, 857, 859, 863, 877, 881, 883,
2255 887, 907, 911, 919, 929, 937, 941, 947,
2256 953, 967, 971, 977, 983, 991, 997, -103
2257};
2258
2259/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002260 * Small divisors test (X must be positive)
2261 *
2262 * Return values:
2263 * 0: no small factor (possible prime, more tests needed)
2264 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002265 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002266 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002267 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002268static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002269{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002270 int ret = 0;
2271 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002273
Paul Bakker5121ce52009-01-03 21:22:43 +00002274 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002275 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002276
2277 for( i = 0; small_prime[i] > 0; i++ )
2278 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002279 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002280 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002281
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002282 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002283
2284 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002285 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002286 }
2287
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002288cleanup:
2289 return( ret );
2290}
2291
2292/*
2293 * Miller-Rabin pseudo-primality test (HAC 4.24)
2294 */
Janos Follath72d555d2018-09-03 14:45:23 +01002295static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002296 int (*f_rng)(void *, unsigned char *, size_t),
2297 void *p_rng )
2298{
Pascal Junodb99183d2015-03-11 16:49:45 +01002299 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002300 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002301 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002302
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002303 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2304 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002305
Paul Bakker5121ce52009-01-03 21:22:43 +00002306 /*
2307 * W = |X| - 1
2308 * R = W >> lsb( W )
2309 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002310 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2311 s = mbedtls_mpi_lsb( &W );
2312 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2313 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002314
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002315 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002316
Janos Follath72d555d2018-09-03 14:45:23 +01002317 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002318 {
2319 /*
2320 * pick a random A, 1 < A < |X| - 1
2321 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002322 count = 0;
2323 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002324 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002325
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002326 j = mbedtls_mpi_bitlen( &A );
2327 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002328 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002329 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002330 }
2331
2332 if (count++ > 30) {
Jens Wiklanderb2aa9382019-01-17 13:30:57 +01002333 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2334 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002335 }
2336
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002337 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2338 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002339
2340 /*
2341 * A = A^R mod |X|
2342 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002343 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002345 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2346 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002347 continue;
2348
2349 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002350 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002351 {
2352 /*
2353 * A = A * A mod |X|
2354 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002355 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2356 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002358 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002359 break;
2360
2361 j++;
2362 }
2363
2364 /*
2365 * not prime if A != |X| - 1 or A == 1
2366 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2368 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002369 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002370 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002371 break;
2372 }
2373 }
2374
2375cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2377 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002378
2379 return( ret );
2380}
2381
2382/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002383 * Pseudo-primality test: small factors, then Miller-Rabin
2384 */
Darryl Green94759f62018-10-16 15:09:19 +01002385static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002386 int (*f_rng)(void *, unsigned char *, size_t),
2387 void *p_rng )
2388{
2389 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002390 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002391
2392 XX.s = 1;
2393 XX.n = X->n;
2394 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2397 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2398 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002400 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002401 return( 0 );
2402
2403 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2404 {
2405 if( ret == 1 )
2406 return( 0 );
2407
2408 return( ret );
2409 }
2410
Janos Follath72d555d2018-09-03 14:45:23 +01002411 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2412}
2413
2414/*
2415 * Pseudo-primality test, error probability 2^-80
2416 */
2417int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2418 int (*f_rng)(void *, unsigned char *, size_t),
2419 void *p_rng )
2420{
2421 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002422}
2423
2424/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002425 * Prime number generation
2426 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002427int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002428 int (*f_rng)(void *, unsigned char *, size_t),
2429 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002430{
Paul Bakker23986e52011-04-24 08:57:21 +00002431 int ret;
2432 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002433 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434 mbedtls_mpi_uint r;
2435 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002436
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002437 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2438 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002439
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002441
2442 n = BITS_TO_LIMBS( nbits );
2443
Janos Follath72d555d2018-09-03 14:45:23 +01002444 /*
2445 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2446 */
2447 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2448 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2449 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002451 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002452
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002453 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002454 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002455
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002456 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002457
2458 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002459
2460 if( dh_flag == 0 )
2461 {
Janos Follath72d555d2018-09-03 14:45:23 +01002462 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002463 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002464 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002465 goto cleanup;
2466
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002467 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002468 }
2469 }
2470 else
2471 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002472 /*
2473 * An necessary condition for Y and X = 2Y + 1 to be prime
2474 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2475 * Make sure it is satisfied, while keeping X = 3 mod 4
2476 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002477
2478 X->p[0] |= 2;
2479
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002480 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002481 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002482 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002483 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002484 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002485
2486 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002487 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2488 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002489
2490 while( 1 )
2491 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002492 /*
2493 * First, check small factors for X and Y
2494 * before doing Miller-Rabin on any of them
2495 */
2496 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2497 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002498 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2499 == 0 &&
2500 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2501 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002502 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002503 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002504 }
2505
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002506 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002507 goto cleanup;
2508
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002509 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002510 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002511 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2512 * so up Y by 6 and X by 12.
2513 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002514 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2515 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002516 }
2517 }
2518
2519cleanup:
2520
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002521 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002522
2523 return( ret );
2524}
2525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002526#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002527
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002528#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002529
Paul Bakker23986e52011-04-24 08:57:21 +00002530#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002531
2532static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2533{
2534 { 693, 609, 21 },
2535 { 1764, 868, 28 },
2536 { 768454923, 542167814, 1 }
2537};
2538
Paul Bakker5121ce52009-01-03 21:22:43 +00002539/*
2540 * Checkup routine
2541 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002542int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002543{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002544 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002545 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002546
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002547 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2548 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002549
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002550 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002551 "EFE021C2645FD1DC586E69184AF4A31E" \
2552 "D5F53E93B5F123FA41680867BA110131" \
2553 "944FE7952E2517337780CB0DB80E61AA" \
2554 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2555
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002556 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002557 "B2E7EFD37075B9F03FF989C7C5051C20" \
2558 "34D2A323810251127E7BF8625A4F49A5" \
2559 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2560 "5B5C25763222FEFCCFC38B832366C29E" ) );
2561
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002563 "0066A198186C18C10B2F5ED9B522752A" \
2564 "9830B69916E535C8F047518A889A43A5" \
2565 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2566
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002567 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002568
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002569 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002570 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2571 "9E857EA95A03512E2BAE7391688D264A" \
2572 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2573 "8001B72E848A38CAE1C65F78E56ABDEF" \
2574 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2575 "ECF677152EF804370C1A305CAF3B5BF1" \
2576 "30879B56C61DE584A0F53A2447A51E" ) );
2577
2578 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002579 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002580
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002581 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002582 {
2583 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002584 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002585
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002586 ret = 1;
2587 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002588 }
2589
2590 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002591 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002593 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002594
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002595 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002596 "256567336059E52CAE22925474705F39A94" ) );
2597
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002598 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002599 "6613F26162223DF488E9CD48CC132C7A" \
2600 "0AC93C701B001B092E4E5B9F73BCD27B" \
2601 "9EE50D0657C77F374E903CDFA4C642" ) );
2602
2603 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002604 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002605
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002606 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2607 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002608 {
2609 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002610 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002611
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002612 ret = 1;
2613 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002614 }
2615
2616 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002617 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002619 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002620
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002621 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002622 "36E139AEA55215609D2816998ED020BB" \
2623 "BD96C37890F65171D948E9BC7CBAA4D9" \
2624 "325D24D6A3C12710F10A09FA08AB87" ) );
2625
2626 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002627 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002628
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002629 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002630 {
2631 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002632 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002633
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002634 ret = 1;
2635 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002636 }
2637
2638 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002639 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002640
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002641 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002642
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002643 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002644 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2645 "C3DBA76456363A10869622EAC2DD84EC" \
2646 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2647
2648 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002649 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002650
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002651 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002652 {
2653 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002654 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002655
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002656 ret = 1;
2657 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002658 }
2659
2660 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002661 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002662
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002663 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002664 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002665
Paul Bakker66d5d072014-06-17 16:39:18 +02002666 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002667 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002668 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2669 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002670
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002671 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002672
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002673 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002674 {
2675 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002676 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002677
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002678 ret = 1;
2679 goto cleanup;
2680 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002681 }
2682
2683 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002684 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002685
Paul Bakker5121ce52009-01-03 21:22:43 +00002686cleanup:
2687
2688 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002689 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002690
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002691 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2692 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002693
2694 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002695 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002696
2697 return( ret );
2698}
2699
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002700#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002701
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002702#endif /* MBEDTLS_BIGNUM_C */