blob: bc3491cdef15fa2ec654ec22984eefe14b38db4f [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;
Gilles Peskine54c30462021-01-27 22:30:43 +01001194 if( n > A->n )
1195 {
1196 /* B >= (2^ciL)^n > A */
1197 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1198 goto cleanup;
1199 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001200
Gilles Peskinefa85cc22020-06-08 22:50:35 +02001201 carry = mpi_sub_hlp( n, X->p, B->p );
1202 if( carry != 0 )
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001203 {
Gilles Peskinefa85cc22020-06-08 22:50:35 +02001204 /* Propagate the carry to the first nonzero limb of X. */
1205 for( ; n < X->n && X->p[n] == 0; n++ )
1206 --X->p[n];
1207 /* If we ran out of space for the carry, it means that the result
1208 * is negative. */
1209 if( n == X->n )
Gilles Peskine91070e42020-07-23 01:16:46 +02001210 {
1211 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1212 goto cleanup;
1213 }
Gilles Peskinefa85cc22020-06-08 22:50:35 +02001214 --X->p[n];
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001215 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001216
1217cleanup:
1218
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001219 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001220
1221 return( ret );
1222}
1223
1224/*
1225 * Signed addition: X = A + B
1226 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001227int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001228{
1229 int ret, s = A->s;
1230
1231 if( A->s * B->s < 0 )
1232 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001233 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001234 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001235 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001236 X->s = s;
1237 }
1238 else
1239 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001240 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001241 X->s = -s;
1242 }
1243 }
1244 else
1245 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001246 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001247 X->s = s;
1248 }
1249
1250cleanup:
1251
1252 return( ret );
1253}
1254
1255/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001256 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001257 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001258int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001259{
1260 int ret, s = A->s;
1261
1262 if( A->s * B->s > 0 )
1263 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001264 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001265 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001266 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001267 X->s = s;
1268 }
1269 else
1270 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001271 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001272 X->s = -s;
1273 }
1274 }
1275 else
1276 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001277 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001278 X->s = s;
1279 }
1280
1281cleanup:
1282
1283 return( ret );
1284}
1285
1286/*
1287 * Signed addition: X = A + b
1288 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001289int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001290{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001291 mbedtls_mpi _B;
1292 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001293
1294 p[0] = ( b < 0 ) ? -b : b;
1295 _B.s = ( b < 0 ) ? -1 : 1;
1296 _B.n = 1;
1297 _B.p = p;
1298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001299 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001300}
1301
1302/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001303 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001304 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001305int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001306{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001307 mbedtls_mpi _B;
1308 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001309
1310 p[0] = ( b < 0 ) ? -b : b;
1311 _B.s = ( b < 0 ) ? -1 : 1;
1312 _B.n = 1;
1313 _B.p = p;
1314
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001315 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001316}
1317
1318/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001319 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001320 */
1321static
1322#if defined(__APPLE__) && defined(__arm__)
1323/*
1324 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1325 * appears to need this to prevent bad ARM code generation at -O3.
1326 */
1327__attribute__ ((noinline))
1328#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001329void 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 +00001330{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001331 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001332
1333#if defined(MULADDC_HUIT)
1334 for( ; i >= 8; i -= 8 )
1335 {
1336 MULADDC_INIT
1337 MULADDC_HUIT
1338 MULADDC_STOP
1339 }
1340
1341 for( ; i > 0; i-- )
1342 {
1343 MULADDC_INIT
1344 MULADDC_CORE
1345 MULADDC_STOP
1346 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001347#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001348 for( ; i >= 16; i -= 16 )
1349 {
1350 MULADDC_INIT
1351 MULADDC_CORE MULADDC_CORE
1352 MULADDC_CORE MULADDC_CORE
1353 MULADDC_CORE MULADDC_CORE
1354 MULADDC_CORE MULADDC_CORE
1355
1356 MULADDC_CORE MULADDC_CORE
1357 MULADDC_CORE MULADDC_CORE
1358 MULADDC_CORE MULADDC_CORE
1359 MULADDC_CORE MULADDC_CORE
1360 MULADDC_STOP
1361 }
1362
1363 for( ; i >= 8; i -= 8 )
1364 {
1365 MULADDC_INIT
1366 MULADDC_CORE MULADDC_CORE
1367 MULADDC_CORE MULADDC_CORE
1368
1369 MULADDC_CORE MULADDC_CORE
1370 MULADDC_CORE MULADDC_CORE
1371 MULADDC_STOP
1372 }
1373
1374 for( ; i > 0; i-- )
1375 {
1376 MULADDC_INIT
1377 MULADDC_CORE
1378 MULADDC_STOP
1379 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001380#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001381
1382 t++;
1383
1384 do {
1385 *d += c; c = ( *d < c ); d++;
1386 }
1387 while( c != 0 );
1388}
1389
1390/*
1391 * Baseline multiplication: X = A * B (HAC 14.12)
1392 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001393int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001394{
Paul Bakker23986e52011-04-24 08:57:21 +00001395 int ret;
1396 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001397 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001398
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001400
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001401 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1402 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001403
Paul Bakker23986e52011-04-24 08:57:21 +00001404 for( i = A->n; i > 0; i-- )
1405 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001406 break;
1407
Paul Bakker23986e52011-04-24 08:57:21 +00001408 for( j = B->n; j > 0; j-- )
1409 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001410 break;
1411
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001412 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1413 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001414
Paul Bakker23986e52011-04-24 08:57:21 +00001415 for( i++; j > 0; j-- )
1416 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001417
1418 X->s = A->s * B->s;
1419
1420cleanup:
1421
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001422 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001423
1424 return( ret );
1425}
1426
1427/*
1428 * Baseline multiplication: X = A * b
1429 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001430int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001431{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001432 mbedtls_mpi _B;
1433 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001434
1435 _B.s = 1;
1436 _B.n = 1;
1437 _B.p = p;
1438 p[0] = b;
1439
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001440 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001441}
1442
1443/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001444 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1445 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001446 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001447static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1448 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001449{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001450#if defined(MBEDTLS_HAVE_UDBL)
1451 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001452#else
Simon Butcher9803d072016-01-03 00:24:34 +00001453 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1454 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001455 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1456 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001457 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001458#endif
1459
Simon Butcher15b15d12015-11-26 19:35:03 +00001460 /*
1461 * Check for overflow
1462 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001463 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001464 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001465 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001466
Simon Butcherf5ba0452015-12-27 23:01:55 +00001467 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001468 }
1469
1470#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001471 dividend = (mbedtls_t_udbl) u1 << biL;
1472 dividend |= (mbedtls_t_udbl) u0;
1473 quotient = dividend / d;
1474 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1475 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1476
1477 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001478 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001479
1480 return (mbedtls_mpi_uint) quotient;
1481#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001482
1483 /*
1484 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1485 * Vol. 2 - Seminumerical Algorithms, Knuth
1486 */
1487
1488 /*
1489 * Normalize the divisor, d, and dividend, u0, u1
1490 */
1491 s = mbedtls_clz( d );
1492 d = d << s;
1493
1494 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001495 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001496 u0 = u0 << s;
1497
1498 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001499 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001500
1501 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001502 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001503
1504 /*
1505 * Find the first quotient and remainder
1506 */
1507 q1 = u1 / d1;
1508 r0 = u1 - d1 * q1;
1509
1510 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1511 {
1512 q1 -= 1;
1513 r0 += d1;
1514
1515 if ( r0 >= radix ) break;
1516 }
1517
Simon Butcherf5ba0452015-12-27 23:01:55 +00001518 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001519 q0 = rAX / d1;
1520 r0 = rAX - q0 * d1;
1521
1522 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1523 {
1524 q0 -= 1;
1525 r0 += d1;
1526
1527 if ( r0 >= radix ) break;
1528 }
1529
1530 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001531 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001532
1533 quotient = q1 * radix + q0;
1534
1535 return quotient;
1536#endif
1537}
1538
1539/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001540 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001541 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001542int 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 +00001543{
Paul Bakker23986e52011-04-24 08:57:21 +00001544 int ret;
1545 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001546 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001547
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001548 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1549 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001550
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001551 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1552 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001554 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001555 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001556 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1557 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001558 return( 0 );
1559 }
1560
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001561 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1562 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001563 X.s = Y.s = 1;
1564
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001565 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1566 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1567 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1568 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001569
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001570 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001571 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001572 {
1573 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001574 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1575 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001576 }
1577 else k = 0;
1578
1579 n = X.n - 1;
1580 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001581 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001582
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001583 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001584 {
1585 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001586 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001587 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001588 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001589
1590 for( i = n; i > t ; i-- )
1591 {
1592 if( X.p[i] >= Y.p[t] )
1593 Z.p[i - t - 1] = ~0;
1594 else
1595 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001596 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1597 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001598 }
1599
1600 Z.p[i - t - 1]++;
1601 do
1602 {
1603 Z.p[i - t - 1]--;
1604
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001605 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001606 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001607 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001608 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001609
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001610 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001611 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1612 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001613 T2.p[2] = X.p[i];
1614 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001615 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001617 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1618 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1619 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001620
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001621 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001622 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001623 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1624 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1625 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001626 Z.p[i - t - 1]--;
1627 }
1628 }
1629
1630 if( Q != NULL )
1631 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001632 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001633 Q->s = A->s * B->s;
1634 }
1635
1636 if( R != NULL )
1637 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001638 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001639 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001640 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001641
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001642 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001643 R->s = 1;
1644 }
1645
1646cleanup:
1647
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001648 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1649 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001650
1651 return( ret );
1652}
1653
1654/*
1655 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001656 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001657int 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 +00001658{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001659 mbedtls_mpi _B;
1660 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001661
1662 p[0] = ( b < 0 ) ? -b : b;
1663 _B.s = ( b < 0 ) ? -1 : 1;
1664 _B.n = 1;
1665 _B.p = p;
1666
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001667 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001668}
1669
1670/*
1671 * Modulo: R = A mod B
1672 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001673int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001674{
1675 int ret;
1676
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001677 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1678 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001679
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001680 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001682 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1683 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001684
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001685 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1686 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001687
1688cleanup:
1689
1690 return( ret );
1691}
1692
1693/*
1694 * Modulo: r = A mod b
1695 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001696int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001697{
Paul Bakker23986e52011-04-24 08:57:21 +00001698 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001699 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001700
1701 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001702 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001703
1704 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001705 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001706
1707 /*
1708 * handle trivial cases
1709 */
1710 if( b == 1 )
1711 {
1712 *r = 0;
1713 return( 0 );
1714 }
1715
1716 if( b == 2 )
1717 {
1718 *r = A->p[0] & 1;
1719 return( 0 );
1720 }
1721
1722 /*
1723 * general case
1724 */
Paul Bakker23986e52011-04-24 08:57:21 +00001725 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001726 {
Paul Bakker23986e52011-04-24 08:57:21 +00001727 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001728 y = ( y << biH ) | ( x >> biH );
1729 z = y / b;
1730 y -= z * b;
1731
1732 x <<= biH;
1733 y = ( y << biH ) | ( x >> biH );
1734 z = y / b;
1735 y -= z * b;
1736 }
1737
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001738 /*
1739 * If A is negative, then the current y represents a negative value.
1740 * Flipping it to the positive side.
1741 */
1742 if( A->s < 0 && y != 0 )
1743 y = b - y;
1744
Paul Bakker5121ce52009-01-03 21:22:43 +00001745 *r = y;
1746
1747 return( 0 );
1748}
1749
1750/*
1751 * Fast Montgomery initialization (thanks to Tom St Denis)
1752 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001753static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001754{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001756 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001757
1758 x = m0;
1759 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001760
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001761 for( i = biL; i >= 8; i /= 2 )
1762 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001763
1764 *mm = ~x + 1;
1765}
1766
Gilles Peskined108d072020-06-04 15:00:49 +02001767/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1768 *
1769 * \param[in,out] A One of the numbers to multiply.
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001770 * It must have at least as many limbs as N
1771 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskined108d072020-06-04 15:00:49 +02001772 * On successful completion, A contains the result of
1773 * the multiplication A * B * R^-1 mod N where
1774 * R = (2^ciL)^n.
1775 * \param[in] B One of the numbers to multiply.
1776 * It must be nonzero and must not have more limbs than N
1777 * (B->n <= N->n).
1778 * \param[in] N The modulo. N must be odd.
1779 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1780 * This is -N^-1 mod 2^ciL.
1781 * \param[in,out] T A bignum for temporary storage.
1782 * It must be at least twice the limb size of N plus 2
1783 * (T->n >= 2 * (N->n + 1)).
1784 * Its initial content is unused and
1785 * its final content is indeterminate.
1786 * Note that unlike the usual convention in the library
1787 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00001788 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001789static 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 +02001790 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001791{
Paul Bakker23986e52011-04-24 08:57:21 +00001792 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001793 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001794
1795 memset( T->p, 0, T->n * ciL );
1796
1797 d = T->p;
1798 n = N->n;
1799 m = ( B->n < n ) ? B->n : n;
1800
1801 for( i = 0; i < n; i++ )
1802 {
1803 /*
1804 * T = (T + u0*B + u1*N) / 2^biL
1805 */
1806 u0 = A->p[i];
1807 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1808
1809 mpi_mul_hlp( m, B->p, d, u0 );
1810 mpi_mul_hlp( n, N->p, d, u1 );
1811
1812 *d++ = u0; d[n + 1] = 0;
1813 }
1814
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001815 /* At this point, d is either the desired result or the desired result
1816 * plus N. We now potentially subtract N, avoiding leaking whether the
1817 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001818
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001819 /* Copy the n least significant limbs of d to A, so that
1820 * A = d if d < N (recall that N has n limbs). */
1821 memcpy( A->p, d, n * ciL );
Gilles Peskinef3317e62020-06-09 10:39:38 +02001822 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001823 * do the calculation without using conditional tests. */
1824 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine7ff812e2020-06-04 21:05:24 +02001825 d[n] += 1;
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001826 d[n] -= mpi_sub_hlp( n, d, N->p );
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001827 /* If d0 < N then d < (2^biL)^n
1828 * so d[n] == 0 and we want to keep A as it is.
1829 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
1830 * so d[n] == 1 and we want to set A to the result of the subtraction
1831 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
1832 * This exactly corresponds to a conditional assignment. */
1833 mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001834}
1835
1836/*
1837 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskined108d072020-06-04 15:00:49 +02001838 *
1839 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001840 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001841static 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 +00001842{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001843 mbedtls_mpi_uint z = 1;
1844 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001845
Paul Bakker8ddb6452013-02-27 14:56:33 +01001846 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001847 U.p = &z;
1848
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001849 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001850}
1851
1852/*
1853 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1854 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001855int 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 +00001856{
Paul Bakker23986e52011-04-24 08:57:21 +00001857 int ret;
1858 size_t wbits, wsize, one = 1;
1859 size_t i, j, nblimbs;
1860 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001861 mbedtls_mpi_uint ei, mm, state;
Daniel Otte19394602020-08-21 12:34:29 +02001862 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001863 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001864
Hanno Becker930ec7d2018-03-09 10:48:00 +00001865 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001866 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001867
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001868 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1869 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001870
Chris Jones8b1f65e2020-11-25 15:12:39 +00001871 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
1872 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
1873 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1874
Paul Bakkerf6198c12012-05-16 08:02:29 +00001875 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001876 * Init temps and window size
1877 */
1878 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1880 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001881 memset( W, 0, sizeof( W ) );
1882
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001883 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001884
1885 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1886 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1887
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001888#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001889 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1890 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001891#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001892
Paul Bakker5121ce52009-01-03 21:22:43 +00001893 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1895 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1896 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001897
1898 /*
Paul Bakker50546922012-05-19 08:40:49 +00001899 * Compensate for negative A (and correct at the end)
1900 */
1901 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001902 if( neg )
1903 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001904 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001905 Apos.s = 1;
1906 A = &Apos;
1907 }
1908
1909 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001910 * If 1st call, pre-compute R^2 mod N
1911 */
1912 if( _RR == NULL || _RR->p == NULL )
1913 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001914 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1915 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1916 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001917
1918 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001919 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001920 }
1921 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001922 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001923
1924 /*
1925 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1926 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001927 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1928 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001929 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001930 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001931
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001932 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001933
1934 /*
1935 * X = R^2 * R^-1 mod N = R mod N
1936 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001937 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001938 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001939
1940 if( wsize > 1 )
1941 {
1942 /*
1943 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1944 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001945 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001946
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001947 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1948 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001949
1950 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001951 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001952
Paul Bakker5121ce52009-01-03 21:22:43 +00001953 /*
1954 * W[i] = W[i - 1] * W[1]
1955 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001956 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001957 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001958 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1959 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001960
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001961 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001962 }
1963 }
1964
1965 nblimbs = E->n;
1966 bufsize = 0;
1967 nbits = 0;
1968 wbits = 0;
1969 state = 0;
1970
1971 while( 1 )
1972 {
1973 if( bufsize == 0 )
1974 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001975 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001976 break;
1977
Paul Bakker0d7702c2013-10-29 16:18:35 +01001978 nblimbs--;
1979
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001980 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001981 }
1982
1983 bufsize--;
1984
1985 ei = (E->p[nblimbs] >> bufsize) & 1;
1986
1987 /*
1988 * skip leading 0s
1989 */
1990 if( ei == 0 && state == 0 )
1991 continue;
1992
1993 if( ei == 0 && state == 1 )
1994 {
1995 /*
1996 * out of window, square X
1997 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001998 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001999 continue;
2000 }
2001
2002 /*
2003 * add ei to current window
2004 */
2005 state = 2;
2006
2007 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002008 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002009
2010 if( nbits == wsize )
2011 {
2012 /*
2013 * X = X^wsize R^-1 mod N
2014 */
2015 for( i = 0; i < wsize; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002016 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002017
2018 /*
2019 * X = X * W[wbits] R^-1 mod N
2020 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002021 mpi_montmul( X, &W[wbits], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
2023 state--;
2024 nbits = 0;
2025 wbits = 0;
2026 }
2027 }
2028
2029 /*
2030 * process the remaining bits
2031 */
2032 for( i = 0; i < nbits; i++ )
2033 {
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002034 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002035
2036 wbits <<= 1;
2037
Paul Bakker66d5d072014-06-17 16:39:18 +02002038 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002039 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002040 }
2041
2042 /*
2043 * X = A^E * R * R^-1 mod N = A^E mod N
2044 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002045 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002046
Hanno Beckera4af1c42017-04-18 09:07:45 +01002047 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002048 {
2049 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002050 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002051 }
2052
Paul Bakker5121ce52009-01-03 21:22:43 +00002053cleanup:
2054
Paul Bakker66d5d072014-06-17 16:39:18 +02002055 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002056 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002057
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002059
Paul Bakker75a28602014-03-31 12:08:17 +02002060 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002061 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002062
2063 return( ret );
2064}
2065
Paul Bakker5121ce52009-01-03 21:22:43 +00002066/*
2067 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2068 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002069int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002070{
Paul Bakker23986e52011-04-24 08:57:21 +00002071 int ret;
2072 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002073 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002074
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002075 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002076
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002077 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2078 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002079
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002080 lz = mbedtls_mpi_lsb( &TA );
2081 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002082
Paul Bakker66d5d072014-06-17 16:39:18 +02002083 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002084 lz = lzt;
2085
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002086 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2087 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002088
Paul Bakker5121ce52009-01-03 21:22:43 +00002089 TA.s = TB.s = 1;
2090
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002091 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002092 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002093 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2094 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002095
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002096 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002097 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002098 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2099 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002100 }
2101 else
2102 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002103 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2104 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002105 }
2106 }
2107
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002108 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2109 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002110
2111cleanup:
2112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002113 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002114
2115 return( ret );
2116}
2117
Paul Bakker33dc46b2014-04-30 16:11:39 +02002118/*
2119 * Fill X with size bytes of random.
2120 *
2121 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002122 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002123 * deterministic, eg for tests).
2124 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002125int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002126 int (*f_rng)(void *, unsigned char *, size_t),
2127 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002128{
Paul Bakker23986e52011-04-24 08:57:21 +00002129 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002130 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02002131
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002132 if( size > MBEDTLS_MPI_MAX_SIZE )
2133 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002134
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002135 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2136 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002137
2138cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01002139 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002140 return( ret );
2141}
2142
Paul Bakker5121ce52009-01-03 21:22:43 +00002143/*
2144 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2145 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002146int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002147{
2148 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002149 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002150
Hanno Becker4bcb4912017-04-18 15:49:39 +01002151 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002152 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002153
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002154 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2155 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2156 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002157
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002158 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002161 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002162 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002163 goto cleanup;
2164 }
2165
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002166 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2167 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2168 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2169 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002170
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002171 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2172 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2173 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2174 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002175
2176 do
2177 {
2178 while( ( TU.p[0] & 1 ) == 0 )
2179 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002180 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002181
2182 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2183 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2185 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002186 }
2187
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2189 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002190 }
2191
2192 while( ( TV.p[0] & 1 ) == 0 )
2193 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002194 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002195
2196 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2197 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2199 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002200 }
2201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002202 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2203 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002204 }
2205
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002207 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002208 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2209 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2210 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002211 }
2212 else
2213 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002214 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2215 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2216 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002217 }
2218 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002219 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002220
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002221 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2222 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002223
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002224 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2225 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002227 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002228
2229cleanup:
2230
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002231 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2232 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2233 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002234
2235 return( ret );
2236}
2237
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002238#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002239
Paul Bakker5121ce52009-01-03 21:22:43 +00002240static const int small_prime[] =
2241{
2242 3, 5, 7, 11, 13, 17, 19, 23,
2243 29, 31, 37, 41, 43, 47, 53, 59,
2244 61, 67, 71, 73, 79, 83, 89, 97,
2245 101, 103, 107, 109, 113, 127, 131, 137,
2246 139, 149, 151, 157, 163, 167, 173, 179,
2247 181, 191, 193, 197, 199, 211, 223, 227,
2248 229, 233, 239, 241, 251, 257, 263, 269,
2249 271, 277, 281, 283, 293, 307, 311, 313,
2250 317, 331, 337, 347, 349, 353, 359, 367,
2251 373, 379, 383, 389, 397, 401, 409, 419,
2252 421, 431, 433, 439, 443, 449, 457, 461,
2253 463, 467, 479, 487, 491, 499, 503, 509,
2254 521, 523, 541, 547, 557, 563, 569, 571,
2255 577, 587, 593, 599, 601, 607, 613, 617,
2256 619, 631, 641, 643, 647, 653, 659, 661,
2257 673, 677, 683, 691, 701, 709, 719, 727,
2258 733, 739, 743, 751, 757, 761, 769, 773,
2259 787, 797, 809, 811, 821, 823, 827, 829,
2260 839, 853, 857, 859, 863, 877, 881, 883,
2261 887, 907, 911, 919, 929, 937, 941, 947,
2262 953, 967, 971, 977, 983, 991, 997, -103
2263};
2264
2265/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002266 * Small divisors test (X must be positive)
2267 *
2268 * Return values:
2269 * 0: no small factor (possible prime, more tests needed)
2270 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002271 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002272 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002273 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002274static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002275{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002276 int ret = 0;
2277 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002278 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002279
Paul Bakker5121ce52009-01-03 21:22:43 +00002280 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002281 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002282
2283 for( i = 0; small_prime[i] > 0; i++ )
2284 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002285 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002286 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002287
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002289
2290 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002291 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002292 }
2293
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002294cleanup:
2295 return( ret );
2296}
2297
2298/*
2299 * Miller-Rabin pseudo-primality test (HAC 4.24)
2300 */
Janos Follath72d555d2018-09-03 14:45:23 +01002301static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002302 int (*f_rng)(void *, unsigned char *, size_t),
2303 void *p_rng )
2304{
Pascal Junodb99183d2015-03-11 16:49:45 +01002305 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002306 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002308
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002309 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2310 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002311
Paul Bakker5121ce52009-01-03 21:22:43 +00002312 /*
2313 * W = |X| - 1
2314 * R = W >> lsb( W )
2315 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002316 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2317 s = mbedtls_mpi_lsb( &W );
2318 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2319 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002320
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002321 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002322
Janos Follath72d555d2018-09-03 14:45:23 +01002323 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002324 {
2325 /*
2326 * pick a random A, 1 < A < |X| - 1
2327 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002328 count = 0;
2329 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002330 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002331
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002332 j = mbedtls_mpi_bitlen( &A );
2333 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002334 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002335 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002336 }
2337
2338 if (count++ > 30) {
Jens Wiklanderb2aa9382019-01-17 13:30:57 +01002339 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2340 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002341 }
2342
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002343 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2344 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002345
2346 /*
2347 * A = A^R mod |X|
2348 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002349 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002350
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002351 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2352 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002353 continue;
2354
2355 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002356 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002357 {
2358 /*
2359 * A = A * A mod |X|
2360 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002361 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2362 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002363
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002364 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002365 break;
2366
2367 j++;
2368 }
2369
2370 /*
2371 * not prime if A != |X| - 1 or A == 1
2372 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002373 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2374 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002375 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002377 break;
2378 }
2379 }
2380
2381cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002382 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2383 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002384
2385 return( ret );
2386}
2387
2388/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002389 * Pseudo-primality test: small factors, then Miller-Rabin
2390 */
Darryl Green94759f62018-10-16 15:09:19 +01002391static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002392 int (*f_rng)(void *, unsigned char *, size_t),
2393 void *p_rng )
2394{
2395 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002397
2398 XX.s = 1;
2399 XX.n = X->n;
2400 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002401
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002402 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2403 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2404 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002406 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002407 return( 0 );
2408
2409 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2410 {
2411 if( ret == 1 )
2412 return( 0 );
2413
2414 return( ret );
2415 }
2416
Janos Follath72d555d2018-09-03 14:45:23 +01002417 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2418}
2419
2420/*
2421 * Pseudo-primality test, error probability 2^-80
2422 */
2423int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2424 int (*f_rng)(void *, unsigned char *, size_t),
2425 void *p_rng )
2426{
2427 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002428}
2429
2430/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002431 * Prime number generation
2432 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002433int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002434 int (*f_rng)(void *, unsigned char *, size_t),
2435 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002436{
Paul Bakker23986e52011-04-24 08:57:21 +00002437 int ret;
2438 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002439 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440 mbedtls_mpi_uint r;
2441 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002443 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2444 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002446 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002447
2448 n = BITS_TO_LIMBS( nbits );
2449
Janos Follath72d555d2018-09-03 14:45:23 +01002450 /*
2451 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2452 */
2453 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2454 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2455 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002457 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002458
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002459 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002460 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002461
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002462 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002463
2464 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002465
2466 if( dh_flag == 0 )
2467 {
Janos Follath72d555d2018-09-03 14:45:23 +01002468 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002469 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002470 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002471 goto cleanup;
2472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002474 }
2475 }
2476 else
2477 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002478 /*
2479 * An necessary condition for Y and X = 2Y + 1 to be prime
2480 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2481 * Make sure it is satisfied, while keeping X = 3 mod 4
2482 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002483
2484 X->p[0] |= 2;
2485
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002486 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002487 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002488 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002489 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002490 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002491
2492 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002493 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2494 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002495
2496 while( 1 )
2497 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002498 /*
2499 * First, check small factors for X and Y
2500 * before doing Miller-Rabin on any of them
2501 */
2502 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2503 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002504 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2505 == 0 &&
2506 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2507 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002508 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002509 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002510 }
2511
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002512 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002513 goto cleanup;
2514
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002515 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002516 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002517 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2518 * so up Y by 6 and X by 12.
2519 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002520 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2521 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002522 }
2523 }
2524
2525cleanup:
2526
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002527 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002528
2529 return( ret );
2530}
2531
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002532#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002533
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002534#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002535
Paul Bakker23986e52011-04-24 08:57:21 +00002536#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002537
2538static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2539{
2540 { 693, 609, 21 },
2541 { 1764, 868, 28 },
2542 { 768454923, 542167814, 1 }
2543};
2544
Paul Bakker5121ce52009-01-03 21:22:43 +00002545/*
2546 * Checkup routine
2547 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002548int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002549{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002550 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002551 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002552
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002553 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2554 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002555
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002556 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002557 "EFE021C2645FD1DC586E69184AF4A31E" \
2558 "D5F53E93B5F123FA41680867BA110131" \
2559 "944FE7952E2517337780CB0DB80E61AA" \
2560 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2561
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002563 "B2E7EFD37075B9F03FF989C7C5051C20" \
2564 "34D2A323810251127E7BF8625A4F49A5" \
2565 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2566 "5B5C25763222FEFCCFC38B832366C29E" ) );
2567
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002568 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002569 "0066A198186C18C10B2F5ED9B522752A" \
2570 "9830B69916E535C8F047518A889A43A5" \
2571 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2572
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002573 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002574
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002575 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002576 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2577 "9E857EA95A03512E2BAE7391688D264A" \
2578 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2579 "8001B72E848A38CAE1C65F78E56ABDEF" \
2580 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2581 "ECF677152EF804370C1A305CAF3B5BF1" \
2582 "30879B56C61DE584A0F53A2447A51E" ) );
2583
2584 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002585 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002586
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002587 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002588 {
2589 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002590 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002591
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002592 ret = 1;
2593 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002594 }
2595
2596 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002597 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002598
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002599 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002600
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002601 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002602 "256567336059E52CAE22925474705F39A94" ) );
2603
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002604 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002605 "6613F26162223DF488E9CD48CC132C7A" \
2606 "0AC93C701B001B092E4E5B9F73BCD27B" \
2607 "9EE50D0657C77F374E903CDFA4C642" ) );
2608
2609 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002610 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002612 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2613 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002614 {
2615 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002616 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002617
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002618 ret = 1;
2619 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002620 }
2621
2622 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002623 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002624
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002625 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002627 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002628 "36E139AEA55215609D2816998ED020BB" \
2629 "BD96C37890F65171D948E9BC7CBAA4D9" \
2630 "325D24D6A3C12710F10A09FA08AB87" ) );
2631
2632 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002633 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002635 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002636 {
2637 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002638 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002639
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002640 ret = 1;
2641 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002642 }
2643
2644 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002645 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002646
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002647 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002648
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002649 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002650 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2651 "C3DBA76456363A10869622EAC2DD84EC" \
2652 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2653
2654 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002655 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002656
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002657 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002658 {
2659 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002660 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002661
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002662 ret = 1;
2663 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002664 }
2665
2666 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002667 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002668
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002669 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002670 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002671
Paul Bakker66d5d072014-06-17 16:39:18 +02002672 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002673 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002674 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2675 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002676
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002677 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002678
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002679 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002680 {
2681 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002682 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002683
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002684 ret = 1;
2685 goto cleanup;
2686 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002687 }
2688
2689 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002690 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002691
Paul Bakker5121ce52009-01-03 21:22:43 +00002692cleanup:
2693
2694 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002695 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002697 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2698 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002699
2700 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002701 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002702
2703 return( ret );
2704}
2705
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002706#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002707
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002708#endif /* MBEDTLS_BIGNUM_C */