blob: c4eb7b04b61a044f76581cdc9a2fc019c72d3f10 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Bence Szépkúti44bfbe32020-08-19 16:54:51 +02004 * Copyright The Mbed TLS Contributors
Bence Szépkúti4e9f7122020-06-05 13:02:18 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +020012 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000024 *
Bence Szépkúti4e9f7122020-06-05 13:02:18 +020025 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
Paul Bakker5121ce52009-01-03 21:22:43 +000045 */
Simon Butcher15b15d12015-11-26 19:35:03 +000046
Paul Bakker5121ce52009-01-03 21:22:43 +000047/*
Simon Butcher15b15d12015-11-26 19:35:03 +000048 * The following sources were referenced in the design of this Multi-precision
49 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000050 *
Simon Butcher15b15d12015-11-26 19:35:03 +000051 * [1] Handbook of Applied Cryptography - 1997
52 * Menezes, van Oorschot and Vanstone
53 *
54 * [2] Multi-Precision Math
55 * Tom St Denis
56 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
57 *
58 * [3] GNU Multi-Precision Arithmetic Library
59 * https://gmplib.org/manual/index.html
60 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000061 */
Paul Bakker5121ce52009-01-03 21:22:43 +000062
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020063#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000064#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020065#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020066#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020067#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000068
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020069#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000070
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000071#include "mbedtls/bignum.h"
72#include "mbedtls/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000073
Rich Evans00ab4702015-02-06 13:43:58 +000074#include <string.h>
75
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020076#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000077#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020078#else
Rich Evans00ab4702015-02-06 13:43:58 +000079#include <stdio.h>
80#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020081#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020082#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020083#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020084#endif
85
Paul Bakker34617722014-06-13 17:20:13 +020086/* Implementation that should never be optimized out by the compiler */
Alexey Skalozube17a8da2016-01-13 17:19:33 +020087static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) {
Alexey Skalozub3d53f412016-01-13 16:53:40 +020088 volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0;
Paul Bakker34617722014-06-13 17:20:13 +020089}
90
Hanno Becker88807112017-10-18 12:41:30 +010091/* Implementation that should never be optimized out by the compiler */
92static void mbedtls_zeroize( void *v, size_t n ) {
93 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
94}
95
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020096#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000097#define biL (ciL << 3) /* bits in limb */
98#define biH (ciL << 2) /* half limb size */
99
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100100#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
101
Paul Bakker5121ce52009-01-03 21:22:43 +0000102/*
103 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200104 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +0000105 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200106#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
107#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +0000108
109/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000110 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000111 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200112void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000113{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000114 if( X == NULL )
115 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000116
Paul Bakker6c591fa2011-05-05 11:49:20 +0000117 X->s = 1;
118 X->n = 0;
119 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000120}
121
122/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000123 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000124 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000126{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000127 if( X == NULL )
128 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000129
Paul Bakker6c591fa2011-05-05 11:49:20 +0000130 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000131 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200132 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200133 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000134 }
135
Paul Bakker6c591fa2011-05-05 11:49:20 +0000136 X->s = 1;
137 X->n = 0;
138 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000139}
140
141/*
142 * Enlarge to the specified number of limbs
143 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000145{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000147
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200149 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000150
Paul Bakker5121ce52009-01-03 21:22:43 +0000151 if( X->n < nblimbs )
152 {
Simon Butcher29176892016-05-20 00:19:09 +0100153 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200154 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000155
Paul Bakker5121ce52009-01-03 21:22:43 +0000156 if( X->p != NULL )
157 {
158 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200159 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000161 }
162
163 X->n = nblimbs;
164 X->p = p;
165 }
166
167 return( 0 );
168}
169
170/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100171 * Resize down as much as possible,
172 * while keeping at least the specified number of limbs
173 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100177 size_t i;
178
Gilles Peskine6a269672020-01-20 21:17:43 +0100179 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100180 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine774c1632020-01-21 13:59:51 +0100182 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100183
184 for( i = X->n - 1; i > 0; i-- )
185 if( X->p[i] != 0 )
186 break;
187 i++;
188
189 if( i < nblimbs )
190 i = nblimbs;
191
Simon Butcher29176892016-05-20 00:19:09 +0100192 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200193 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100194
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100195 if( X->p != NULL )
196 {
197 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200198 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100200 }
201
202 X->n = i;
203 X->p = p;
204
205 return( 0 );
206}
207
208/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000209 * Copy the contents of Y into X
210 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000212{
Paul Bakker23986e52011-04-24 08:57:21 +0000213 int ret;
214 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000215
216 if( X == Y )
217 return( 0 );
218
Gilles Peskine2aeab872020-01-20 21:12:50 +0100219 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200220 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200222 return( 0 );
223 }
224
Paul Bakker5121ce52009-01-03 21:22:43 +0000225 for( i = Y->n - 1; i > 0; i-- )
226 if( Y->p[i] != 0 )
227 break;
228 i++;
229
230 X->s = Y->s;
231
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200232 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000233
234 memset( X->p, 0, X->n * ciL );
235 memcpy( X->p, Y->p, i * ciL );
236
237cleanup:
238
239 return( ret );
240}
241
242/*
243 * Swap the contents of X and Y
244 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200245void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000246{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000248
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249 memcpy( &T, X, sizeof( mbedtls_mpi ) );
250 memcpy( X, Y, sizeof( mbedtls_mpi ) );
251 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000252}
253
254/*
Gilles Peskine3c44c652020-06-04 19:14:58 +0200255 * Conditionally assign dest = src, without leaking information
256 * about whether the assignment was made or not.
257 * dest and src must be arrays of limbs of size n.
258 * assign must be 0 or 1.
259 */
260static void mpi_safe_cond_assign( size_t n,
261 mbedtls_mpi_uint *dest,
262 const mbedtls_mpi_uint *src,
263 unsigned char assign )
264{
265 size_t i;
266 for( i = 0; i < n; i++ )
267 dest[i] = dest[i] * ( 1 - assign ) + src[i] * assign;
268}
269
270/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100271 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100272 * about whether the assignment was made or not.
273 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100274 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200275int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100276{
277 int ret = 0;
278 size_t i;
279
Pascal Junodb99183d2015-03-11 16:49:45 +0100280 /* make sure assign is 0 or 1 in a time-constant manner */
281 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100284
Paul Bakker66d5d072014-06-17 16:39:18 +0200285 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286
Gilles Peskine3c44c652020-06-04 19:14:58 +0200287 mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100288
Gilles Peskine3c44c652020-06-04 19:14:58 +0200289 for( i = Y->n; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200290 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100291
292cleanup:
293 return( ret );
294}
295
296/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100297 * Conditionally swap X and Y, without leaking information
298 * about whether the swap was made or not.
299 * Here it is not ok to simply swap the pointers, which whould lead to
300 * different memory access patterns when X and Y are used afterwards.
301 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200302int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100303{
304 int ret, s;
305 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100307
308 if( X == Y )
309 return( 0 );
310
Pascal Junodb99183d2015-03-11 16:49:45 +0100311 /* make sure swap is 0 or 1 in a time-constant manner */
312 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100313
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200314 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
315 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100316
317 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200318 X->s = X->s * ( 1 - swap ) + Y->s * swap;
319 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100320
321
322 for( i = 0; i < X->n; i++ )
323 {
324 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200325 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
326 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100327 }
328
329cleanup:
330 return( ret );
331}
332
333/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000334 * Set value from integer
335 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000337{
338 int ret;
339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200340 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000341 memset( X->p, 0, X->n * ciL );
342
343 X->p[0] = ( z < 0 ) ? -z : z;
344 X->s = ( z < 0 ) ? -1 : 1;
345
346cleanup:
347
348 return( ret );
349}
350
351/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000352 * Get a specific bit
353 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200354int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000355{
356 if( X->n * biL <= pos )
357 return( 0 );
358
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200359 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000360}
361
Gilles Peskine220cc172018-11-20 16:47:47 +0100362/* Get a specific byte, without range checks. */
363#define GET_BYTE( X, i ) \
364 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
365
Paul Bakker2f5947e2011-05-18 15:47:11 +0000366/*
367 * Set a bit to a specific value of 0 or 1
368 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000370{
371 int ret = 0;
372 size_t off = pos / biL;
373 size_t idx = pos % biL;
374
375 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200376 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200377
Paul Bakker2f5947e2011-05-18 15:47:11 +0000378 if( X->n * biL <= pos )
379 {
380 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200381 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000384 }
385
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200386 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
387 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000388
389cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200390
Paul Bakker2f5947e2011-05-18 15:47:11 +0000391 return( ret );
392}
393
394/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200395 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000396 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000398{
Paul Bakker23986e52011-04-24 08:57:21 +0000399 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000400
401 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000402 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000403 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
404 return( count );
405
406 return( 0 );
407}
408
409/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000410 * Count leading zero bits in a given integer
411 */
412static size_t mbedtls_clz( const mbedtls_mpi_uint x )
413{
414 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100415 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000416
417 for( j = 0; j < biL; j++ )
418 {
419 if( x & mask ) break;
420
421 mask >>= 1;
422 }
423
424 return j;
425}
426
427/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200428 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000429 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200430size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000431{
Paul Bakker23986e52011-04-24 08:57:21 +0000432 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000433
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200434 if( X->n == 0 )
435 return( 0 );
436
Paul Bakker5121ce52009-01-03 21:22:43 +0000437 for( i = X->n - 1; i > 0; i-- )
438 if( X->p[i] != 0 )
439 break;
440
Simon Butcher15b15d12015-11-26 19:35:03 +0000441 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
Paul Bakker23986e52011-04-24 08:57:21 +0000443 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000444}
445
446/*
447 * Return the total size in bytes
448 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000450{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200451 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000452}
453
454/*
455 * Convert an ASCII character to digit value
456 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000458{
459 *d = 255;
460
461 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
462 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
463 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 if( *d >= (mbedtls_mpi_uint) radix )
466 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000467
468 return( 0 );
469}
470
471/*
472 * Import from an ASCII string
473 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000475{
Paul Bakker23986e52011-04-24 08:57:21 +0000476 int ret;
477 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200478 mbedtls_mpi_uint d;
479 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
481 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000485
Paul Bakkerff60ee62010-03-16 21:09:09 +0000486 slen = strlen( s );
487
Paul Bakker5121ce52009-01-03 21:22:43 +0000488 if( radix == 16 )
489 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100490 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200491 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
492
Paul Bakkerff60ee62010-03-16 21:09:09 +0000493 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200495 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
496 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000497
Paul Bakker23986e52011-04-24 08:57:21 +0000498 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000499 {
Paul Bakker23986e52011-04-24 08:57:21 +0000500 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000501 {
502 X->s = -1;
503 break;
504 }
505
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200506 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200507 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000508 }
509 }
510 else
511 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000513
Paul Bakkerff60ee62010-03-16 21:09:09 +0000514 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000515 {
516 if( i == 0 && s[i] == '-' )
517 {
518 X->s = -1;
519 continue;
520 }
521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
523 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000524
525 if( X->s == 1 )
526 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000528 }
529 else
530 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200531 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000532 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000533 }
534 }
535
536cleanup:
537
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
540 return( ret );
541}
542
543/*
Ron Eldore6cbfc32018-11-20 14:07:01 +0200544 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000545 */
Ron Eldore6cbfc32018-11-20 14:07:01 +0200546static int mpi_write_hlp( mbedtls_mpi *X, int radix,
547 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000548{
549 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550 mbedtls_mpi_uint r;
Ron Eldore6cbfc32018-11-20 14:07:01 +0200551 size_t length = 0;
552 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000553
Ron Eldore6cbfc32018-11-20 14:07:01 +0200554 do
555 {
556 if( length >= buflen )
557 {
558 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
559 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000560
Ron Eldore6cbfc32018-11-20 14:07:01 +0200561 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
562 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
563 /*
564 * Write the residue in the current position, as an ASCII character.
565 */
566 if( r < 0xA )
567 *(--p_end) = (char)( '0' + r );
568 else
569 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000570
Ron Eldore6cbfc32018-11-20 14:07:01 +0200571 length++;
572 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000573
Ron Eldore6cbfc32018-11-20 14:07:01 +0200574 memmove( *p, p_end, length );
575 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000576
577cleanup:
578
579 return( ret );
580}
581
582/*
583 * Export into an ASCII string
584 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100585int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
586 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000587{
Paul Bakker23986e52011-04-24 08:57:21 +0000588 int ret = 0;
589 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000590 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000592
593 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000595
Hanno Beckera277d4c2019-02-04 09:45:07 +0000596 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
597 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
598 * `n`. If radix > 4, this might be a strict
599 * overapproximation of the number of
600 * radix-adic digits needed to present `n`. */
601 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
602 * present `n`. */
603
Janos Follath216e7382019-03-06 13:43:02 +0000604 n += 1; /* Terminating null byte */
Hanno Beckera277d4c2019-02-04 09:45:07 +0000605 n += 1; /* Compensate for the divisions above, which round down `n`
606 * in case it's not even. */
607 n += 1; /* Potential '-'-sign. */
608 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
609 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000610
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100611 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000612 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100613 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200614 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000615 }
616
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100617 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200618 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000619
620 if( X->s == -1 )
Hanno Beckereff335d2019-02-01 16:41:30 +0000621 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000622 *p++ = '-';
Hanno Beckereff335d2019-02-01 16:41:30 +0000623 buflen--;
624 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000625
626 if( radix == 16 )
627 {
Paul Bakker23986e52011-04-24 08:57:21 +0000628 int c;
629 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000630
Paul Bakker23986e52011-04-24 08:57:21 +0000631 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000632 {
Paul Bakker23986e52011-04-24 08:57:21 +0000633 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000634 {
Paul Bakker23986e52011-04-24 08:57:21 +0000635 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000636
Paul Bakker6c343d72014-07-10 14:36:19 +0200637 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000638 continue;
639
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000640 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000641 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000642 k = 1;
643 }
644 }
645 }
646 else
647 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000649
650 if( T.s == -1 )
651 T.s = 1;
652
Ron Eldore6cbfc32018-11-20 14:07:01 +0200653 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000654 }
655
656 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100657 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000658
659cleanup:
660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000662
663 return( ret );
664}
665
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000667/*
668 * Read X from an opened file
669 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000671{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000673 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000674 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000675 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000676 * Buffer should have space for (short) label and decimal formatted MPI,
677 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000678 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200679 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000680
681 memset( s, 0, sizeof( s ) );
682 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000684
685 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000686 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000688
Hanno Beckerb2034b72017-04-26 11:46:46 +0100689 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
690 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
692 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100693 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000694 if( mpi_get_digit( &d, radix, *p ) != 0 )
695 break;
696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000698}
699
700/*
701 * Write X into an opened file (or stdout if fout == NULL)
702 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000704{
Paul Bakker23986e52011-04-24 08:57:21 +0000705 int ret;
706 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000707 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000708 * Buffer should have space for (short) label and decimal formatted MPI,
709 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000710 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200711 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000712
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100713 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000714
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100715 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000716
717 if( p == NULL ) p = "";
718
719 plen = strlen( p );
720 slen = strlen( s );
721 s[slen++] = '\r';
722 s[slen++] = '\n';
723
724 if( fout != NULL )
725 {
726 if( fwrite( p, 1, plen, fout ) != plen ||
727 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000729 }
730 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000732
733cleanup:
734
735 return( ret );
736}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000738
739/*
740 * Import X from unsigned binary data, big endian
741 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200742int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000743{
Paul Bakker23986e52011-04-24 08:57:21 +0000744 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100745 size_t i, j;
746 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000747
Hanno Becker073c1992017-10-17 15:17:27 +0100748 /* Ensure that target MPI has exactly the necessary number of limbs */
749 if( X->n != limbs )
750 {
751 mbedtls_mpi_free( X );
752 mbedtls_mpi_init( X );
753 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
754 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000755
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200756 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000757
Hanno Becker073c1992017-10-17 15:17:27 +0100758 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200759 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000760
761cleanup:
762
763 return( ret );
764}
765
766/*
767 * Export X into unsigned binary data, big endian
768 */
Gilles Peskine220cc172018-11-20 16:47:47 +0100769int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
770 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000771{
Gilles Peskine220cc172018-11-20 16:47:47 +0100772 size_t stored_bytes = X->n * ciL;
773 size_t bytes_to_copy;
774 unsigned char *p;
775 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000776
Gilles Peskine220cc172018-11-20 16:47:47 +0100777 if( stored_bytes < buflen )
778 {
779 /* There is enough space in the output buffer. Write initial
780 * null bytes and record the position at which to start
781 * writing the significant bytes. In this case, the execution
782 * trace of this function does not depend on the value of the
783 * number. */
784 bytes_to_copy = stored_bytes;
785 p = buf + buflen - stored_bytes;
786 memset( buf, 0, buflen - stored_bytes );
787 }
788 else
789 {
790 /* The output buffer is smaller than the allocated size of X.
791 * However X may fit if its leading bytes are zero. */
792 bytes_to_copy = buflen;
793 p = buf;
794 for( i = bytes_to_copy; i < stored_bytes; i++ )
795 {
796 if( GET_BYTE( X, i ) != 0 )
797 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
798 }
799 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000800
Gilles Peskine220cc172018-11-20 16:47:47 +0100801 for( i = 0; i < bytes_to_copy; i++ )
802 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000803
804 return( 0 );
805}
806
807/*
808 * Left-shift: X <<= count
809 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200810int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000811{
Paul Bakker23986e52011-04-24 08:57:21 +0000812 int ret;
813 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200814 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000815
816 v0 = count / (biL );
817 t1 = count & (biL - 1);
818
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200819 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000820
Paul Bakkerf9688572011-05-05 10:00:45 +0000821 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200822 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000823
824 ret = 0;
825
826 /*
827 * shift by count / limb_size
828 */
829 if( v0 > 0 )
830 {
Paul Bakker23986e52011-04-24 08:57:21 +0000831 for( i = X->n; i > v0; i-- )
832 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000833
Paul Bakker23986e52011-04-24 08:57:21 +0000834 for( ; i > 0; i-- )
835 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000836 }
837
838 /*
839 * shift by count % limb_size
840 */
841 if( t1 > 0 )
842 {
843 for( i = v0; i < X->n; i++ )
844 {
845 r1 = X->p[i] >> (biL - t1);
846 X->p[i] <<= t1;
847 X->p[i] |= r0;
848 r0 = r1;
849 }
850 }
851
852cleanup:
853
854 return( ret );
855}
856
857/*
858 * Right-shift: X >>= count
859 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200860int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000861{
Paul Bakker23986e52011-04-24 08:57:21 +0000862 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200863 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000864
865 v0 = count / biL;
866 v1 = count & (biL - 1);
867
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100868 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200869 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100870
Paul Bakker5121ce52009-01-03 21:22:43 +0000871 /*
872 * shift by count / limb_size
873 */
874 if( v0 > 0 )
875 {
876 for( i = 0; i < X->n - v0; i++ )
877 X->p[i] = X->p[i + v0];
878
879 for( ; i < X->n; i++ )
880 X->p[i] = 0;
881 }
882
883 /*
884 * shift by count % limb_size
885 */
886 if( v1 > 0 )
887 {
Paul Bakker23986e52011-04-24 08:57:21 +0000888 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000889 {
Paul Bakker23986e52011-04-24 08:57:21 +0000890 r1 = X->p[i - 1] << (biL - v1);
891 X->p[i - 1] >>= v1;
892 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000893 r0 = r1;
894 }
895 }
896
897 return( 0 );
898}
899
900/*
901 * Compare unsigned values
902 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200903int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000904{
Paul Bakker23986e52011-04-24 08:57:21 +0000905 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000906
Paul Bakker23986e52011-04-24 08:57:21 +0000907 for( i = X->n; i > 0; i-- )
908 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000909 break;
910
Paul Bakker23986e52011-04-24 08:57:21 +0000911 for( j = Y->n; j > 0; j-- )
912 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000913 break;
914
Paul Bakker23986e52011-04-24 08:57:21 +0000915 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000916 return( 0 );
917
918 if( i > j ) return( 1 );
919 if( j > i ) return( -1 );
920
Paul Bakker23986e52011-04-24 08:57:21 +0000921 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000922 {
Paul Bakker23986e52011-04-24 08:57:21 +0000923 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
924 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000925 }
926
927 return( 0 );
928}
929
930/*
931 * Compare signed values
932 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200933int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000934{
Paul Bakker23986e52011-04-24 08:57:21 +0000935 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000936
Paul Bakker23986e52011-04-24 08:57:21 +0000937 for( i = X->n; i > 0; i-- )
938 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000939 break;
940
Paul Bakker23986e52011-04-24 08:57:21 +0000941 for( j = Y->n; j > 0; j-- )
942 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000943 break;
944
Paul Bakker23986e52011-04-24 08:57:21 +0000945 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000946 return( 0 );
947
948 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000949 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000950
951 if( X->s > 0 && Y->s < 0 ) return( 1 );
952 if( Y->s > 0 && X->s < 0 ) return( -1 );
953
Paul Bakker23986e52011-04-24 08:57:21 +0000954 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000955 {
Paul Bakker23986e52011-04-24 08:57:21 +0000956 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
957 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000958 }
959
960 return( 0 );
961}
962
Janos Follath3173a532019-10-14 09:09:32 +0100963/** Decide if an integer is less than the other, without branches.
964 *
965 * \param x First integer.
966 * \param y Second integer.
967 *
968 * \return 1 if \p x is less than \p y, 0 otherwise
969 */
Janos Follathc3b376e2019-10-11 14:21:53 +0100970static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
971 const mbedtls_mpi_uint y )
Janos Follathe0187b92019-09-05 14:47:19 +0100972{
973 mbedtls_mpi_uint ret;
974 mbedtls_mpi_uint cond;
975
976 /*
977 * Check if the most significant bits (MSB) of the operands are different.
978 */
979 cond = ( x ^ y );
980 /*
981 * If the MSB are the same then the difference x-y will be negative (and
982 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
983 */
984 ret = ( x - y ) & ~cond;
985 /*
986 * If the MSB are different, then the operand with the MSB of 1 is the
987 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
988 * the MSB of y is 0.)
989 */
990 ret |= y & cond;
991
992
Janos Follathdb9f4492019-10-14 08:59:14 +0100993 ret = ret >> ( biL - 1 );
Janos Follathe0187b92019-09-05 14:47:19 +0100994
Janos Follath58239612019-10-29 15:08:46 +0000995 return (unsigned) ret;
Janos Follathe0187b92019-09-05 14:47:19 +0100996}
997
998/*
999 * Compare signed values in constant time
1000 */
Janos Follathc3b376e2019-10-11 14:21:53 +01001001int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1002 unsigned *ret )
Janos Follathe0187b92019-09-05 14:47:19 +01001003{
1004 size_t i;
Janos Follatha2b9a962019-10-28 12:23:18 +00001005 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath8ec2a952019-10-28 12:31:34 +00001006 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathe0187b92019-09-05 14:47:19 +01001007
1008 if( X->n != Y->n )
1009 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1010
1011 /*
Janos Follath51ed14e2019-10-28 12:12:15 +00001012 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1013 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathe0187b92019-09-05 14:47:19 +01001014 */
Janos Follath8ec2a952019-10-28 12:31:34 +00001015 X_is_negative = ( X->s & 2 ) >> 1;
1016 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follathc3b376e2019-10-11 14:21:53 +01001017
1018 /*
1019 * If the signs are different, then the positive operand is the bigger.
Janos Follath8ec2a952019-10-28 12:31:34 +00001020 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1021 * is false if X is positive (X_is_negative == 0).
Janos Follathc3b376e2019-10-11 14:21:53 +01001022 */
Janos Follath8ec2a952019-10-28 12:31:34 +00001023 cond = ( X_is_negative ^ Y_is_negative );
1024 *ret = cond & X_is_negative;
Janos Follathc3b376e2019-10-11 14:21:53 +01001025
1026 /*
Janos Follatha2b9a962019-10-28 12:23:18 +00001027 * This is a constant-time function. We might have the result, but we still
Janos Follathc3b376e2019-10-11 14:21:53 +01001028 * need to go through the loop. Record if we have the result already.
1029 */
Janos Follathe0187b92019-09-05 14:47:19 +01001030 done = cond;
1031
1032 for( i = X->n; i > 0; i-- )
1033 {
1034 /*
Janos Follathb4edac52019-11-05 12:24:52 +00001035 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1036 * X and Y are negative.
Janos Follathc3b376e2019-10-11 14:21:53 +01001037 *
1038 * Again even if we can make a decision, we just mark the result and
1039 * the fact that we are done and continue looping.
Janos Follathe0187b92019-09-05 14:47:19 +01001040 */
Janos Follathb4edac52019-11-05 12:24:52 +00001041 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1042 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathcff9e6e2019-10-28 12:37:21 +00001043 done |= cond;
Janos Follathe0187b92019-09-05 14:47:19 +01001044
1045 /*
Janos Follathb4edac52019-11-05 12:24:52 +00001046 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1047 * X and Y are positive.
Janos Follathc3b376e2019-10-11 14:21:53 +01001048 *
1049 * Again even if we can make a decision, we just mark the result and
1050 * the fact that we are done and continue looping.
Janos Follathe0187b92019-09-05 14:47:19 +01001051 */
Janos Follathb4edac52019-11-05 12:24:52 +00001052 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1053 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathcff9e6e2019-10-28 12:37:21 +00001054 done |= cond;
Janos Follathe0187b92019-09-05 14:47:19 +01001055 }
1056
1057 return( 0 );
1058}
1059
Paul Bakker5121ce52009-01-03 21:22:43 +00001060/*
1061 * Compare signed values
1062 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001063int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001064{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001065 mbedtls_mpi Y;
1066 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001067
1068 *p = ( z < 0 ) ? -z : z;
1069 Y.s = ( z < 0 ) ? -1 : 1;
1070 Y.n = 1;
1071 Y.p = p;
1072
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001073 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001074}
1075
1076/*
1077 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1078 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001079int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001080{
Paul Bakker23986e52011-04-24 08:57:21 +00001081 int ret;
1082 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001083 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +00001084
1085 if( X == B )
1086 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001087 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001088 }
1089
1090 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001091 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001092
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001093 /*
1094 * X should always be positive as a result of unsigned additions.
1095 */
1096 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001097
Paul Bakker23986e52011-04-24 08:57:21 +00001098 for( j = B->n; j > 0; j-- )
1099 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001100 break;
1101
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001102 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001103
1104 o = B->p; p = X->p; c = 0;
1105
Janos Follath6c922682015-10-30 17:43:11 +01001106 /*
1107 * tmp is used because it might happen that p == o
1108 */
Paul Bakker23986e52011-04-24 08:57:21 +00001109 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001110 {
Janos Follath6c922682015-10-30 17:43:11 +01001111 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001112 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001113 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001114 }
1115
1116 while( c != 0 )
1117 {
1118 if( i >= X->n )
1119 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001120 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001121 p = X->p + i;
1122 }
1123
Paul Bakker2d319fd2012-09-16 21:34:26 +00001124 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001125 }
1126
1127cleanup:
1128
1129 return( ret );
1130}
1131
Gilles Peskinef3317e62020-06-09 10:39:38 +02001132/**
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001133 * Helper for mbedtls_mpi subtraction.
1134 *
1135 * Calculate d - s where d and s have the same size.
1136 * This function operates modulo (2^ciL)^n and returns the carry
1137 * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise).
1138 *
1139 * \param n Number of limbs of \p d and \p s.
1140 * \param[in,out] d On input, the left operand.
1141 * On output, the result of the subtraction:
Gilles Peskinef3317e62020-06-09 10:39:38 +02001142 * \param[in] s The right operand.
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001143 *
1144 * \return 1 if `d < s`.
1145 * 0 if `d >= s`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001146 */
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001147static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1148 mbedtls_mpi_uint *d,
1149 const mbedtls_mpi_uint *s )
Paul Bakker5121ce52009-01-03 21:22:43 +00001150{
Paul Bakker23986e52011-04-24 08:57:21 +00001151 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001152 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001153
1154 for( i = c = 0; i < n; i++, s++, d++ )
1155 {
1156 z = ( *d < c ); *d -= c;
1157 c = ( *d < *s ) + z; *d -= *s;
1158 }
1159
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001160 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001161}
1162
1163/*
Gilles Peskinefa85cc22020-06-08 22:50:35 +02001164 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001165 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001166int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001167{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001168 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001169 int ret;
1170 size_t n;
Gilles Peskinefa85cc22020-06-08 22:50:35 +02001171 mbedtls_mpi_uint carry;
Paul Bakker5121ce52009-01-03 21:22:43 +00001172
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001173 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001174
1175 if( X == B )
1176 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001177 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001178 B = &TB;
1179 }
1180
1181 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001182 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001183
Paul Bakker1ef7a532009-06-20 10:50:55 +00001184 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001185 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001186 */
1187 X->s = 1;
1188
Paul Bakker5121ce52009-01-03 21:22:43 +00001189 ret = 0;
1190
Paul Bakker23986e52011-04-24 08:57:21 +00001191 for( n = B->n; n > 0; n-- )
1192 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001193 break;
1194
Gilles Peskinefa85cc22020-06-08 22:50:35 +02001195 carry = mpi_sub_hlp( n, X->p, B->p );
1196 if( carry != 0 )
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001197 {
Gilles Peskinefa85cc22020-06-08 22:50:35 +02001198 /* Propagate the carry to the first nonzero limb of X. */
1199 for( ; n < X->n && X->p[n] == 0; n++ )
1200 --X->p[n];
1201 /* If we ran out of space for the carry, it means that the result
1202 * is negative. */
1203 if( n == X->n )
Gilles Peskine91070e42020-07-23 01:16:46 +02001204 {
1205 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1206 goto cleanup;
1207 }
Gilles Peskinefa85cc22020-06-08 22:50:35 +02001208 --X->p[n];
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001209 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001210
1211cleanup:
1212
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001213 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001214
1215 return( ret );
1216}
1217
1218/*
1219 * Signed addition: X = A + B
1220 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001221int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001222{
1223 int ret, s = A->s;
1224
1225 if( A->s * B->s < 0 )
1226 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001227 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001228 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001229 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001230 X->s = s;
1231 }
1232 else
1233 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001234 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001235 X->s = -s;
1236 }
1237 }
1238 else
1239 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001240 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001241 X->s = s;
1242 }
1243
1244cleanup:
1245
1246 return( ret );
1247}
1248
1249/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001250 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001251 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001252int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001253{
1254 int ret, s = A->s;
1255
1256 if( A->s * B->s > 0 )
1257 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001258 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001259 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001260 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001261 X->s = s;
1262 }
1263 else
1264 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001265 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001266 X->s = -s;
1267 }
1268 }
1269 else
1270 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001271 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001272 X->s = s;
1273 }
1274
1275cleanup:
1276
1277 return( ret );
1278}
1279
1280/*
1281 * Signed addition: X = A + b
1282 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001283int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001284{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001285 mbedtls_mpi _B;
1286 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001287
1288 p[0] = ( b < 0 ) ? -b : b;
1289 _B.s = ( b < 0 ) ? -1 : 1;
1290 _B.n = 1;
1291 _B.p = p;
1292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001293 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001294}
1295
1296/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001297 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001298 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001299int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001300{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001301 mbedtls_mpi _B;
1302 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001303
1304 p[0] = ( b < 0 ) ? -b : b;
1305 _B.s = ( b < 0 ) ? -1 : 1;
1306 _B.n = 1;
1307 _B.p = p;
1308
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001309 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001310}
1311
1312/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001313 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001314 */
1315static
1316#if defined(__APPLE__) && defined(__arm__)
1317/*
1318 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1319 * appears to need this to prevent bad ARM code generation at -O3.
1320 */
1321__attribute__ ((noinline))
1322#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001323void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001324{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001325 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001326
1327#if defined(MULADDC_HUIT)
1328 for( ; i >= 8; i -= 8 )
1329 {
1330 MULADDC_INIT
1331 MULADDC_HUIT
1332 MULADDC_STOP
1333 }
1334
1335 for( ; i > 0; i-- )
1336 {
1337 MULADDC_INIT
1338 MULADDC_CORE
1339 MULADDC_STOP
1340 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001341#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001342 for( ; i >= 16; i -= 16 )
1343 {
1344 MULADDC_INIT
1345 MULADDC_CORE MULADDC_CORE
1346 MULADDC_CORE MULADDC_CORE
1347 MULADDC_CORE MULADDC_CORE
1348 MULADDC_CORE MULADDC_CORE
1349
1350 MULADDC_CORE MULADDC_CORE
1351 MULADDC_CORE MULADDC_CORE
1352 MULADDC_CORE MULADDC_CORE
1353 MULADDC_CORE MULADDC_CORE
1354 MULADDC_STOP
1355 }
1356
1357 for( ; i >= 8; i -= 8 )
1358 {
1359 MULADDC_INIT
1360 MULADDC_CORE MULADDC_CORE
1361 MULADDC_CORE MULADDC_CORE
1362
1363 MULADDC_CORE MULADDC_CORE
1364 MULADDC_CORE MULADDC_CORE
1365 MULADDC_STOP
1366 }
1367
1368 for( ; i > 0; i-- )
1369 {
1370 MULADDC_INIT
1371 MULADDC_CORE
1372 MULADDC_STOP
1373 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001374#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001375
1376 t++;
1377
1378 do {
1379 *d += c; c = ( *d < c ); d++;
1380 }
1381 while( c != 0 );
1382}
1383
1384/*
1385 * Baseline multiplication: X = A * B (HAC 14.12)
1386 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001387int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001388{
Paul Bakker23986e52011-04-24 08:57:21 +00001389 int ret;
1390 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001393 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001394
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001395 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1396 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001397
Paul Bakker23986e52011-04-24 08:57:21 +00001398 for( i = A->n; i > 0; i-- )
1399 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001400 break;
1401
Paul Bakker23986e52011-04-24 08:57:21 +00001402 for( j = B->n; j > 0; j-- )
1403 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001404 break;
1405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1407 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001408
Paul Bakker23986e52011-04-24 08:57:21 +00001409 for( i++; j > 0; j-- )
1410 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001411
1412 X->s = A->s * B->s;
1413
1414cleanup:
1415
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001416 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001417
1418 return( ret );
1419}
1420
1421/*
1422 * Baseline multiplication: X = A * b
1423 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001424int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001425{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001426 mbedtls_mpi _B;
1427 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001428
1429 _B.s = 1;
1430 _B.n = 1;
1431 _B.p = p;
1432 p[0] = b;
1433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001434 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001435}
1436
1437/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001438 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1439 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001440 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001441static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1442 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001443{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001444#if defined(MBEDTLS_HAVE_UDBL)
1445 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001446#else
Simon Butcher9803d072016-01-03 00:24:34 +00001447 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1448 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001449 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1450 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001451 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001452#endif
1453
Simon Butcher15b15d12015-11-26 19:35:03 +00001454 /*
1455 * Check for overflow
1456 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001457 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001458 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001459 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001460
Simon Butcherf5ba0452015-12-27 23:01:55 +00001461 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001462 }
1463
1464#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001465 dividend = (mbedtls_t_udbl) u1 << biL;
1466 dividend |= (mbedtls_t_udbl) u0;
1467 quotient = dividend / d;
1468 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1469 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1470
1471 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001472 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001473
1474 return (mbedtls_mpi_uint) quotient;
1475#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001476
1477 /*
1478 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1479 * Vol. 2 - Seminumerical Algorithms, Knuth
1480 */
1481
1482 /*
1483 * Normalize the divisor, d, and dividend, u0, u1
1484 */
1485 s = mbedtls_clz( d );
1486 d = d << s;
1487
1488 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001489 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001490 u0 = u0 << s;
1491
1492 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001493 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001494
1495 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001496 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001497
1498 /*
1499 * Find the first quotient and remainder
1500 */
1501 q1 = u1 / d1;
1502 r0 = u1 - d1 * q1;
1503
1504 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1505 {
1506 q1 -= 1;
1507 r0 += d1;
1508
1509 if ( r0 >= radix ) break;
1510 }
1511
Simon Butcherf5ba0452015-12-27 23:01:55 +00001512 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001513 q0 = rAX / d1;
1514 r0 = rAX - q0 * d1;
1515
1516 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1517 {
1518 q0 -= 1;
1519 r0 += d1;
1520
1521 if ( r0 >= radix ) break;
1522 }
1523
1524 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001525 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001526
1527 quotient = q1 * radix + q0;
1528
1529 return quotient;
1530#endif
1531}
1532
1533/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001534 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001535 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001536int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001537{
Paul Bakker23986e52011-04-24 08:57:21 +00001538 int ret;
1539 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001540 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001541
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001542 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1543 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001544
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001545 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1546 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001547
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001548 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001549 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001550 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1551 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001552 return( 0 );
1553 }
1554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001555 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1556 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001557 X.s = Y.s = 1;
1558
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001559 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1560 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1561 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1562 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001563
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001564 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001565 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001566 {
1567 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001568 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1569 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001570 }
1571 else k = 0;
1572
1573 n = X.n - 1;
1574 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001575 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001576
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001577 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001578 {
1579 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001580 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001581 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001582 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001583
1584 for( i = n; i > t ; i-- )
1585 {
1586 if( X.p[i] >= Y.p[t] )
1587 Z.p[i - t - 1] = ~0;
1588 else
1589 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001590 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1591 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001592 }
1593
1594 Z.p[i - t - 1]++;
1595 do
1596 {
1597 Z.p[i - t - 1]--;
1598
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001599 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001600 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001601 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001602 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001603
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001604 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001605 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1606 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001607 T2.p[2] = X.p[i];
1608 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001609 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001610
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001611 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1612 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1613 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001615 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001616 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001617 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1618 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1619 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001620 Z.p[i - t - 1]--;
1621 }
1622 }
1623
1624 if( Q != NULL )
1625 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001626 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001627 Q->s = A->s * B->s;
1628 }
1629
1630 if( R != NULL )
1631 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001632 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001633 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001634 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001637 R->s = 1;
1638 }
1639
1640cleanup:
1641
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001642 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1643 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001644
1645 return( ret );
1646}
1647
1648/*
1649 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001650 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001652{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001653 mbedtls_mpi _B;
1654 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001655
1656 p[0] = ( b < 0 ) ? -b : b;
1657 _B.s = ( b < 0 ) ? -1 : 1;
1658 _B.n = 1;
1659 _B.p = p;
1660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001662}
1663
1664/*
1665 * Modulo: R = A mod B
1666 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001667int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001668{
1669 int ret;
1670
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1672 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001673
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001674 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001676 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1677 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001678
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001679 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1680 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001681
1682cleanup:
1683
1684 return( ret );
1685}
1686
1687/*
1688 * Modulo: r = A mod b
1689 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001690int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001691{
Paul Bakker23986e52011-04-24 08:57:21 +00001692 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001693 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001694
1695 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001696 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001697
1698 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001699 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001700
1701 /*
1702 * handle trivial cases
1703 */
1704 if( b == 1 )
1705 {
1706 *r = 0;
1707 return( 0 );
1708 }
1709
1710 if( b == 2 )
1711 {
1712 *r = A->p[0] & 1;
1713 return( 0 );
1714 }
1715
1716 /*
1717 * general case
1718 */
Paul Bakker23986e52011-04-24 08:57:21 +00001719 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001720 {
Paul Bakker23986e52011-04-24 08:57:21 +00001721 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001722 y = ( y << biH ) | ( x >> biH );
1723 z = y / b;
1724 y -= z * b;
1725
1726 x <<= biH;
1727 y = ( y << biH ) | ( x >> biH );
1728 z = y / b;
1729 y -= z * b;
1730 }
1731
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001732 /*
1733 * If A is negative, then the current y represents a negative value.
1734 * Flipping it to the positive side.
1735 */
1736 if( A->s < 0 && y != 0 )
1737 y = b - y;
1738
Paul Bakker5121ce52009-01-03 21:22:43 +00001739 *r = y;
1740
1741 return( 0 );
1742}
1743
1744/*
1745 * Fast Montgomery initialization (thanks to Tom St Denis)
1746 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001747static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001748{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001749 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001750 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001751
1752 x = m0;
1753 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001754
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001755 for( i = biL; i >= 8; i /= 2 )
1756 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001757
1758 *mm = ~x + 1;
1759}
1760
Gilles Peskined108d072020-06-04 15:00:49 +02001761/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1762 *
1763 * \param[in,out] A One of the numbers to multiply.
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001764 * It must have at least as many limbs as N
1765 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskined108d072020-06-04 15:00:49 +02001766 * On successful completion, A contains the result of
1767 * the multiplication A * B * R^-1 mod N where
1768 * R = (2^ciL)^n.
1769 * \param[in] B One of the numbers to multiply.
1770 * It must be nonzero and must not have more limbs than N
1771 * (B->n <= N->n).
1772 * \param[in] N The modulo. N must be odd.
1773 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1774 * This is -N^-1 mod 2^ciL.
1775 * \param[in,out] T A bignum for temporary storage.
1776 * It must be at least twice the limb size of N plus 2
1777 * (T->n >= 2 * (N->n + 1)).
1778 * Its initial content is unused and
1779 * its final content is indeterminate.
1780 * Note that unlike the usual convention in the library
1781 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00001782 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001783static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001784 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001785{
Paul Bakker23986e52011-04-24 08:57:21 +00001786 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001787 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001788
1789 memset( T->p, 0, T->n * ciL );
1790
1791 d = T->p;
1792 n = N->n;
1793 m = ( B->n < n ) ? B->n : n;
1794
1795 for( i = 0; i < n; i++ )
1796 {
1797 /*
1798 * T = (T + u0*B + u1*N) / 2^biL
1799 */
1800 u0 = A->p[i];
1801 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1802
1803 mpi_mul_hlp( m, B->p, d, u0 );
1804 mpi_mul_hlp( n, N->p, d, u1 );
1805
1806 *d++ = u0; d[n + 1] = 0;
1807 }
1808
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001809 /* At this point, d is either the desired result or the desired result
1810 * plus N. We now potentially subtract N, avoiding leaking whether the
1811 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001812
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001813 /* Copy the n least significant limbs of d to A, so that
1814 * A = d if d < N (recall that N has n limbs). */
1815 memcpy( A->p, d, n * ciL );
Gilles Peskinef3317e62020-06-09 10:39:38 +02001816 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001817 * do the calculation without using conditional tests. */
1818 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine7ff812e2020-06-04 21:05:24 +02001819 d[n] += 1;
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001820 d[n] -= mpi_sub_hlp( n, d, N->p );
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001821 /* If d0 < N then d < (2^biL)^n
1822 * so d[n] == 0 and we want to keep A as it is.
1823 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
1824 * so d[n] == 1 and we want to set A to the result of the subtraction
1825 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
1826 * This exactly corresponds to a conditional assignment. */
1827 mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001828}
1829
1830/*
1831 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskined108d072020-06-04 15:00:49 +02001832 *
1833 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001834 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001835static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001836{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001837 mbedtls_mpi_uint z = 1;
1838 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001839
Paul Bakker8ddb6452013-02-27 14:56:33 +01001840 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001841 U.p = &z;
1842
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001843 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001844}
1845
1846/*
1847 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1848 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001849int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001850{
Paul Bakker23986e52011-04-24 08:57:21 +00001851 int ret;
1852 size_t wbits, wsize, one = 1;
1853 size_t i, j, nblimbs;
1854 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001855 mbedtls_mpi_uint ei, mm, state;
Daniel Otte19394602020-08-21 12:34:29 +02001856 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001857 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001858
Hanno Becker930ec7d2018-03-09 10:48:00 +00001859 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001860 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001861
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001862 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1863 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001864
1865 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001866 * Init temps and window size
1867 */
1868 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001869 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1870 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001871 memset( W, 0, sizeof( W ) );
1872
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001873 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001874
1875 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1876 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1877
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001878#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1880 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001881#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001882
Paul Bakker5121ce52009-01-03 21:22:43 +00001883 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001884 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1885 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1886 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001887
1888 /*
Paul Bakker50546922012-05-19 08:40:49 +00001889 * Compensate for negative A (and correct at the end)
1890 */
1891 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001892 if( neg )
1893 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001895 Apos.s = 1;
1896 A = &Apos;
1897 }
1898
1899 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001900 * If 1st call, pre-compute R^2 mod N
1901 */
1902 if( _RR == NULL || _RR->p == NULL )
1903 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001904 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1905 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1906 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001907
1908 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001909 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001910 }
1911 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001912 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001913
1914 /*
1915 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1916 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001917 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1918 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001919 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001920 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001921
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001922 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001923
1924 /*
1925 * X = R^2 * R^-1 mod N = R mod N
1926 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001927 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001928 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001929
1930 if( wsize > 1 )
1931 {
1932 /*
1933 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1934 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001935 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001936
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001937 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1938 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001939
1940 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001941 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001942
Paul Bakker5121ce52009-01-03 21:22:43 +00001943 /*
1944 * W[i] = W[i - 1] * W[1]
1945 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001946 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001947 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001948 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1949 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001950
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001951 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001952 }
1953 }
1954
1955 nblimbs = E->n;
1956 bufsize = 0;
1957 nbits = 0;
1958 wbits = 0;
1959 state = 0;
1960
1961 while( 1 )
1962 {
1963 if( bufsize == 0 )
1964 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001965 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001966 break;
1967
Paul Bakker0d7702c2013-10-29 16:18:35 +01001968 nblimbs--;
1969
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001970 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001971 }
1972
1973 bufsize--;
1974
1975 ei = (E->p[nblimbs] >> bufsize) & 1;
1976
1977 /*
1978 * skip leading 0s
1979 */
1980 if( ei == 0 && state == 0 )
1981 continue;
1982
1983 if( ei == 0 && state == 1 )
1984 {
1985 /*
1986 * out of window, square X
1987 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001988 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001989 continue;
1990 }
1991
1992 /*
1993 * add ei to current window
1994 */
1995 state = 2;
1996
1997 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001998 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001999
2000 if( nbits == wsize )
2001 {
2002 /*
2003 * X = X^wsize R^-1 mod N
2004 */
2005 for( i = 0; i < wsize; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002006 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002007
2008 /*
2009 * X = X * W[wbits] R^-1 mod N
2010 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002011 mpi_montmul( X, &W[wbits], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002012
2013 state--;
2014 nbits = 0;
2015 wbits = 0;
2016 }
2017 }
2018
2019 /*
2020 * process the remaining bits
2021 */
2022 for( i = 0; i < nbits; i++ )
2023 {
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002024 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002025
2026 wbits <<= 1;
2027
Paul Bakker66d5d072014-06-17 16:39:18 +02002028 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002029 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002030 }
2031
2032 /*
2033 * X = A^E * R * R^-1 mod N = A^E mod N
2034 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002035 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002036
Hanno Beckera4af1c42017-04-18 09:07:45 +01002037 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002038 {
2039 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002040 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002041 }
2042
Paul Bakker5121ce52009-01-03 21:22:43 +00002043cleanup:
2044
Paul Bakker66d5d072014-06-17 16:39:18 +02002045 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002047
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002048 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002049
Paul Bakker75a28602014-03-31 12:08:17 +02002050 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002051 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002052
2053 return( ret );
2054}
2055
Paul Bakker5121ce52009-01-03 21:22:43 +00002056/*
2057 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2058 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002059int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002060{
Paul Bakker23986e52011-04-24 08:57:21 +00002061 int ret;
2062 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002063 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002064
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002065 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002066
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002067 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2068 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002069
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002070 lz = mbedtls_mpi_lsb( &TA );
2071 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002072
Paul Bakker66d5d072014-06-17 16:39:18 +02002073 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002074 lz = lzt;
2075
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2077 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002078
Paul Bakker5121ce52009-01-03 21:22:43 +00002079 TA.s = TB.s = 1;
2080
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002081 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002082 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002083 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2084 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002085
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002086 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002087 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002088 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2089 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002090 }
2091 else
2092 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002093 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2094 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002095 }
2096 }
2097
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002098 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2099 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002100
2101cleanup:
2102
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002103 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002104
2105 return( ret );
2106}
2107
Paul Bakker33dc46b2014-04-30 16:11:39 +02002108/*
2109 * Fill X with size bytes of random.
2110 *
2111 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002112 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002113 * deterministic, eg for tests).
2114 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002115int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002116 int (*f_rng)(void *, unsigned char *, size_t),
2117 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002118{
Paul Bakker23986e52011-04-24 08:57:21 +00002119 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002120 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02002121
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002122 if( size > MBEDTLS_MPI_MAX_SIZE )
2123 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002125 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2126 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002127
2128cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01002129 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002130 return( ret );
2131}
2132
Paul Bakker5121ce52009-01-03 21:22:43 +00002133/*
2134 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2135 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002136int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002137{
2138 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002139 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002140
Hanno Becker4bcb4912017-04-18 15:49:39 +01002141 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002142 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002143
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002144 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2145 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2146 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002147
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002148 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002149
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002150 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002151 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002152 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002153 goto cleanup;
2154 }
2155
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002156 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2157 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2158 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2159 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002160
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002161 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2162 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2163 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2164 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002165
2166 do
2167 {
2168 while( ( TU.p[0] & 1 ) == 0 )
2169 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002170 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002171
2172 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2173 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002174 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2175 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002176 }
2177
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002178 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2179 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002180 }
2181
2182 while( ( TV.p[0] & 1 ) == 0 )
2183 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002185
2186 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2187 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2189 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002190 }
2191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002192 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2193 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002194 }
2195
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002196 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002197 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2199 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2200 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002201 }
2202 else
2203 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002204 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2205 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2206 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002207 }
2208 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002209 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002210
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002211 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2212 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002213
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002214 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2215 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002216
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002217 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002218
2219cleanup:
2220
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002221 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2222 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2223 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002224
2225 return( ret );
2226}
2227
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002228#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002229
Paul Bakker5121ce52009-01-03 21:22:43 +00002230static const int small_prime[] =
2231{
2232 3, 5, 7, 11, 13, 17, 19, 23,
2233 29, 31, 37, 41, 43, 47, 53, 59,
2234 61, 67, 71, 73, 79, 83, 89, 97,
2235 101, 103, 107, 109, 113, 127, 131, 137,
2236 139, 149, 151, 157, 163, 167, 173, 179,
2237 181, 191, 193, 197, 199, 211, 223, 227,
2238 229, 233, 239, 241, 251, 257, 263, 269,
2239 271, 277, 281, 283, 293, 307, 311, 313,
2240 317, 331, 337, 347, 349, 353, 359, 367,
2241 373, 379, 383, 389, 397, 401, 409, 419,
2242 421, 431, 433, 439, 443, 449, 457, 461,
2243 463, 467, 479, 487, 491, 499, 503, 509,
2244 521, 523, 541, 547, 557, 563, 569, 571,
2245 577, 587, 593, 599, 601, 607, 613, 617,
2246 619, 631, 641, 643, 647, 653, 659, 661,
2247 673, 677, 683, 691, 701, 709, 719, 727,
2248 733, 739, 743, 751, 757, 761, 769, 773,
2249 787, 797, 809, 811, 821, 823, 827, 829,
2250 839, 853, 857, 859, 863, 877, 881, 883,
2251 887, 907, 911, 919, 929, 937, 941, 947,
2252 953, 967, 971, 977, 983, 991, 997, -103
2253};
2254
2255/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002256 * Small divisors test (X must be positive)
2257 *
2258 * Return values:
2259 * 0: no small factor (possible prime, more tests needed)
2260 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002261 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002262 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002263 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002265{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002266 int ret = 0;
2267 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002268 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002269
Paul Bakker5121ce52009-01-03 21:22:43 +00002270 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002271 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002272
2273 for( i = 0; small_prime[i] > 0; i++ )
2274 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002275 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002276 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002277
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002278 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002279
2280 if( r == 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
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002284cleanup:
2285 return( ret );
2286}
2287
2288/*
2289 * Miller-Rabin pseudo-primality test (HAC 4.24)
2290 */
Janos Follath72d555d2018-09-03 14:45:23 +01002291static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002292 int (*f_rng)(void *, unsigned char *, size_t),
2293 void *p_rng )
2294{
Pascal Junodb99183d2015-03-11 16:49:45 +01002295 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002296 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002297 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2300 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002301
Paul Bakker5121ce52009-01-03 21:22:43 +00002302 /*
2303 * W = |X| - 1
2304 * R = W >> lsb( W )
2305 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002306 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2307 s = mbedtls_mpi_lsb( &W );
2308 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2309 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002310
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002311 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002312
Janos Follath72d555d2018-09-03 14:45:23 +01002313 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002314 {
2315 /*
2316 * pick a random A, 1 < A < |X| - 1
2317 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002318 count = 0;
2319 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002320 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002321
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002322 j = mbedtls_mpi_bitlen( &A );
2323 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002324 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002325 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002326 }
2327
2328 if (count++ > 30) {
Jens Wiklanderb2aa9382019-01-17 13:30:57 +01002329 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2330 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002331 }
2332
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002333 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2334 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002335
2336 /*
2337 * A = A^R mod |X|
2338 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002339 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2342 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002343 continue;
2344
2345 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002346 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002347 {
2348 /*
2349 * A = A * A mod |X|
2350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002351 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2352 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002354 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002355 break;
2356
2357 j++;
2358 }
2359
2360 /*
2361 * not prime if A != |X| - 1 or A == 1
2362 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002363 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2364 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002365 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002366 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002367 break;
2368 }
2369 }
2370
2371cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002372 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2373 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002374
2375 return( ret );
2376}
2377
2378/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002379 * Pseudo-primality test: small factors, then Miller-Rabin
2380 */
Darryl Green94759f62018-10-16 15:09:19 +01002381static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002382 int (*f_rng)(void *, unsigned char *, size_t),
2383 void *p_rng )
2384{
2385 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002386 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002387
2388 XX.s = 1;
2389 XX.n = X->n;
2390 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002392 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2393 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2394 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002397 return( 0 );
2398
2399 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2400 {
2401 if( ret == 1 )
2402 return( 0 );
2403
2404 return( ret );
2405 }
2406
Janos Follath72d555d2018-09-03 14:45:23 +01002407 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2408}
2409
2410/*
2411 * Pseudo-primality test, error probability 2^-80
2412 */
2413int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2414 int (*f_rng)(void *, unsigned char *, size_t),
2415 void *p_rng )
2416{
2417 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002418}
2419
2420/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002421 * Prime number generation
2422 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002423int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002424 int (*f_rng)(void *, unsigned char *, size_t),
2425 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002426{
Paul Bakker23986e52011-04-24 08:57:21 +00002427 int ret;
2428 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002429 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002430 mbedtls_mpi_uint r;
2431 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002432
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002433 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2434 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002435
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002436 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002437
2438 n = BITS_TO_LIMBS( nbits );
2439
Janos Follath72d555d2018-09-03 14:45:23 +01002440 /*
2441 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2442 */
2443 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2444 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2445 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2446
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002447 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002448
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002449 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002450 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002451
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002452 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002453
2454 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002455
2456 if( dh_flag == 0 )
2457 {
Janos Follath72d555d2018-09-03 14:45:23 +01002458 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002459 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002460 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002461 goto cleanup;
2462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002463 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002464 }
2465 }
2466 else
2467 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002468 /*
2469 * An necessary condition for Y and X = 2Y + 1 to be prime
2470 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2471 * Make sure it is satisfied, while keeping X = 3 mod 4
2472 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002473
2474 X->p[0] |= 2;
2475
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002476 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002477 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002478 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002479 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002480 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002481
2482 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002483 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2484 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002485
2486 while( 1 )
2487 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002488 /*
2489 * First, check small factors for X and Y
2490 * before doing Miller-Rabin on any of them
2491 */
2492 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2493 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002494 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2495 == 0 &&
2496 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2497 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002498 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002499 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002500 }
2501
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002502 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002503 goto cleanup;
2504
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002505 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002506 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002507 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2508 * so up Y by 6 and X by 12.
2509 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002510 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2511 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002512 }
2513 }
2514
2515cleanup:
2516
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002517 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002518
2519 return( ret );
2520}
2521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002522#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002524#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002525
Paul Bakker23986e52011-04-24 08:57:21 +00002526#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002527
2528static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2529{
2530 { 693, 609, 21 },
2531 { 1764, 868, 28 },
2532 { 768454923, 542167814, 1 }
2533};
2534
Paul Bakker5121ce52009-01-03 21:22:43 +00002535/*
2536 * Checkup routine
2537 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002538int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002539{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002540 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002541 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002543 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2544 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002545
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002546 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002547 "EFE021C2645FD1DC586E69184AF4A31E" \
2548 "D5F53E93B5F123FA41680867BA110131" \
2549 "944FE7952E2517337780CB0DB80E61AA" \
2550 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002552 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002553 "B2E7EFD37075B9F03FF989C7C5051C20" \
2554 "34D2A323810251127E7BF8625A4F49A5" \
2555 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2556 "5B5C25763222FEFCCFC38B832366C29E" ) );
2557
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002558 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002559 "0066A198186C18C10B2F5ED9B522752A" \
2560 "9830B69916E535C8F047518A889A43A5" \
2561 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2562
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002563 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002564
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002565 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002566 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2567 "9E857EA95A03512E2BAE7391688D264A" \
2568 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2569 "8001B72E848A38CAE1C65F78E56ABDEF" \
2570 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2571 "ECF677152EF804370C1A305CAF3B5BF1" \
2572 "30879B56C61DE584A0F53A2447A51E" ) );
2573
2574 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002575 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002576
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002577 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002578 {
2579 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002580 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002581
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002582 ret = 1;
2583 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002584 }
2585
2586 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002587 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002588
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002589 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002591 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002592 "256567336059E52CAE22925474705F39A94" ) );
2593
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002594 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002595 "6613F26162223DF488E9CD48CC132C7A" \
2596 "0AC93C701B001B092E4E5B9F73BCD27B" \
2597 "9EE50D0657C77F374E903CDFA4C642" ) );
2598
2599 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002600 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002601
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002602 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2603 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002604 {
2605 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002606 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002607
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002608 ret = 1;
2609 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002610 }
2611
2612 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002613 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002615 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002617 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002618 "36E139AEA55215609D2816998ED020BB" \
2619 "BD96C37890F65171D948E9BC7CBAA4D9" \
2620 "325D24D6A3C12710F10A09FA08AB87" ) );
2621
2622 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002623 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002624
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002625 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002626 {
2627 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002628 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002629
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002630 ret = 1;
2631 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002632 }
2633
2634 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002635 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002636
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002637 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002638
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002639 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002640 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2641 "C3DBA76456363A10869622EAC2DD84EC" \
2642 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2643
2644 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002645 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002646
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002647 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002648 {
2649 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002650 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002651
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002652 ret = 1;
2653 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002654 }
2655
2656 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002657 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002658
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002659 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002660 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002661
Paul Bakker66d5d072014-06-17 16:39:18 +02002662 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002663 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002664 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2665 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002666
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002667 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002669 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002670 {
2671 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002672 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002673
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002674 ret = 1;
2675 goto cleanup;
2676 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002677 }
2678
2679 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002680 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002681
Paul Bakker5121ce52009-01-03 21:22:43 +00002682cleanup:
2683
2684 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002685 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002686
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002687 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2688 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002689
2690 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002691 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002692
2693 return( ret );
2694}
2695
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002696#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002697
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002698#endif /* MBEDTLS_BIGNUM_C */