blob: 593229ecdac85a0ada72b2d5aae6e0a5397a72a9 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050048#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000049
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <string.h>
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020054#else
Rich Evans00ab4702015-02-06 13:43:58 +000055#include <stdio.h>
56#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020058#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020060#endif
61
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020062#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000063#define biL (ciL << 3) /* bits in limb */
64#define biH (ciL << 2) /* half limb size */
65
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010066#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
67
Paul Bakker5121ce52009-01-03 21:22:43 +000068/*
69 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020070 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000071 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020072#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
73#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000074
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050075/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050076static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
77{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050078 mbedtls_platform_zeroize( v, ciL * n );
79}
80
Paul Bakker5121ce52009-01-03 21:22:43 +000081/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000082 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000083 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000085{
Paul Bakker6c591fa2011-05-05 11:49:20 +000086 if( X == NULL )
87 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000088
Paul Bakker6c591fa2011-05-05 11:49:20 +000089 X->s = 1;
90 X->n = 0;
91 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000092}
93
94/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000095 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000096 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020097void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000098{
Paul Bakker6c591fa2011-05-05 11:49:20 +000099 if( X == NULL )
100 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000101
Paul Bakker6c591fa2011-05-05 11:49:20 +0000102 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000103 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200104 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200105 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000106 }
107
Paul Bakker6c591fa2011-05-05 11:49:20 +0000108 X->s = 1;
109 X->n = 0;
110 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000111}
112
113/*
114 * Enlarge to the specified number of limbs
115 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000117{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200118 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200121 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000122
Paul Bakker5121ce52009-01-03 21:22:43 +0000123 if( X->n < nblimbs )
124 {
Simon Butcher29176892016-05-20 00:19:09 +0100125 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200126 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000127
Paul Bakker5121ce52009-01-03 21:22:43 +0000128 if( X->p != NULL )
129 {
130 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200131 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200132 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 }
134
135 X->n = nblimbs;
136 X->p = p;
137 }
138
139 return( 0 );
140}
141
142/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100143 * Resize down as much as possible,
144 * while keeping at least the specified number of limbs
145 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100147{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100149 size_t i;
150
151 /* Actually resize up in this case */
152 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154
155 for( i = X->n - 1; i > 0; i-- )
156 if( X->p[i] != 0 )
157 break;
158 i++;
159
160 if( i < nblimbs )
161 i = nblimbs;
162
Simon Butcher29176892016-05-20 00:19:09 +0100163 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200164 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100165
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100166 if( X->p != NULL )
167 {
168 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200169 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100171 }
172
173 X->n = i;
174 X->p = p;
175
176 return( 0 );
177}
178
179/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000180 * Copy the contents of Y into X
181 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200182int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000183{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100184 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000185 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000186
187 if( X == Y )
188 return( 0 );
189
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200190 if( Y->p == NULL )
191 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200192 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200193 return( 0 );
194 }
195
Paul Bakker5121ce52009-01-03 21:22:43 +0000196 for( i = Y->n - 1; i > 0; i-- )
197 if( Y->p[i] != 0 )
198 break;
199 i++;
200
201 X->s = Y->s;
202
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100203 if( X->n < i )
204 {
205 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
206 }
207 else
208 {
209 memset( X->p + i, 0, ( X->n - i ) * ciL );
210 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000211
Paul Bakker5121ce52009-01-03 21:22:43 +0000212 memcpy( X->p, Y->p, i * ciL );
213
214cleanup:
215
216 return( ret );
217}
218
219/*
220 * Swap the contents of X and Y
221 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000223{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200224 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000225
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200226 memcpy( &T, X, sizeof( mbedtls_mpi ) );
227 memcpy( X, Y, sizeof( mbedtls_mpi ) );
228 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000229}
230
231/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100232 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100233 * about whether the assignment was made or not.
234 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100235 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100237{
238 int ret = 0;
239 size_t i;
240
Pascal Junodb99183d2015-03-11 16:49:45 +0100241 /* make sure assign is 0 or 1 in a time-constant manner */
242 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100243
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200244 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100245
Paul Bakker66d5d072014-06-17 16:39:18 +0200246 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100247
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100248 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200249 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100250
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100251 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200252 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100253
254cleanup:
255 return( ret );
256}
257
258/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100259 * Conditionally swap X and Y, without leaking information
260 * about whether the swap was made or not.
261 * Here it is not ok to simply swap the pointers, which whould lead to
262 * different memory access patterns when X and Y are used afterwards.
263 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200264int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100265{
266 int ret, s;
267 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100269
270 if( X == Y )
271 return( 0 );
272
Pascal Junodb99183d2015-03-11 16:49:45 +0100273 /* make sure swap is 0 or 1 in a time-constant manner */
274 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100275
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200276 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
277 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100278
279 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200280 X->s = X->s * ( 1 - swap ) + Y->s * swap;
281 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100282
283
284 for( i = 0; i < X->n; i++ )
285 {
286 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200287 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
288 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100289 }
290
291cleanup:
292 return( ret );
293}
294
295/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000296 * Set value from integer
297 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200298int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000299{
300 int ret;
301
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200302 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000303 memset( X->p, 0, X->n * ciL );
304
305 X->p[0] = ( z < 0 ) ? -z : z;
306 X->s = ( z < 0 ) ? -1 : 1;
307
308cleanup:
309
310 return( ret );
311}
312
313/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000314 * Get a specific bit
315 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200316int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000317{
318 if( X->n * biL <= pos )
319 return( 0 );
320
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200321 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000322}
323
324/*
325 * Set a bit to a specific value of 0 or 1
326 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000328{
329 int ret = 0;
330 size_t off = pos / biL;
331 size_t idx = pos % biL;
332
333 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200335
Paul Bakker2f5947e2011-05-18 15:47:11 +0000336 if( X->n * biL <= pos )
337 {
338 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200339 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000342 }
343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
345 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000346
347cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200348
Paul Bakker2f5947e2011-05-18 15:47:11 +0000349 return( ret );
350}
351
352/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200353 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000354 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000356{
Paul Bakker23986e52011-04-24 08:57:21 +0000357 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000358
359 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000360 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000361 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
362 return( count );
363
364 return( 0 );
365}
366
367/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000368 * Count leading zero bits in a given integer
369 */
370static size_t mbedtls_clz( const mbedtls_mpi_uint x )
371{
372 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100373 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000374
375 for( j = 0; j < biL; j++ )
376 {
377 if( x & mask ) break;
378
379 mask >>= 1;
380 }
381
382 return j;
383}
384
385/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200386 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200388size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000389{
Paul Bakker23986e52011-04-24 08:57:21 +0000390 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000391
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200392 if( X->n == 0 )
393 return( 0 );
394
Paul Bakker5121ce52009-01-03 21:22:43 +0000395 for( i = X->n - 1; i > 0; i-- )
396 if( X->p[i] != 0 )
397 break;
398
Simon Butcher15b15d12015-11-26 19:35:03 +0000399 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000400
Paul Bakker23986e52011-04-24 08:57:21 +0000401 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000402}
403
404/*
405 * Return the total size in bytes
406 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000408{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200409 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000410}
411
412/*
413 * Convert an ASCII character to digit value
414 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000416{
417 *d = 255;
418
419 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
420 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
421 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
422
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200423 if( *d >= (mbedtls_mpi_uint) radix )
424 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000425
426 return( 0 );
427}
428
429/*
430 * Import from an ASCII string
431 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000433{
Paul Bakker23986e52011-04-24 08:57:21 +0000434 int ret;
435 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200436 mbedtls_mpi_uint d;
437 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000438
439 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200440 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000441
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000443
Paul Bakkerff60ee62010-03-16 21:09:09 +0000444 slen = strlen( s );
445
Paul Bakker5121ce52009-01-03 21:22:43 +0000446 if( radix == 16 )
447 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100448 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200449 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
450
Paul Bakkerff60ee62010-03-16 21:09:09 +0000451 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
454 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000455
Paul Bakker23986e52011-04-24 08:57:21 +0000456 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000457 {
Paul Bakker23986e52011-04-24 08:57:21 +0000458 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000459 {
460 X->s = -1;
461 break;
462 }
463
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200464 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200465 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000466 }
467 }
468 else
469 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000471
Paul Bakkerff60ee62010-03-16 21:09:09 +0000472 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000473 {
474 if( i == 0 && s[i] == '-' )
475 {
476 X->s = -1;
477 continue;
478 }
479
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200480 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
481 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000482
483 if( X->s == 1 )
484 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000486 }
487 else
488 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000490 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000491 }
492 }
493
494cleanup:
495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000497
498 return( ret );
499}
500
501/*
Ron Eldora16fa292018-11-20 14:07:01 +0200502 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000503 */
Ron Eldora16fa292018-11-20 14:07:01 +0200504static int mpi_write_hlp( mbedtls_mpi *X, int radix,
505 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000506{
507 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200509 size_t length = 0;
510 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000511
Ron Eldora16fa292018-11-20 14:07:01 +0200512 do
513 {
514 if( length >= buflen )
515 {
516 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
517 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000518
Ron Eldora16fa292018-11-20 14:07:01 +0200519 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
520 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
521 /*
522 * Write the residue in the current position, as an ASCII character.
523 */
524 if( r < 0xA )
525 *(--p_end) = (char)( '0' + r );
526 else
527 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000528
Ron Eldora16fa292018-11-20 14:07:01 +0200529 length++;
530 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000531
Ron Eldora16fa292018-11-20 14:07:01 +0200532 memmove( *p, p_end, length );
533 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000534
535cleanup:
536
537 return( ret );
538}
539
540/*
541 * Export into an ASCII string
542 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100543int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
544 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000545{
Paul Bakker23986e52011-04-24 08:57:21 +0000546 int ret = 0;
547 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000548 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200549 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000550
551 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200552 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000553
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200554 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000555 if( radix >= 4 ) n >>= 1;
556 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000557 /*
558 * Round up the buffer length to an even value to ensure that there is
559 * enough room for hexadecimal values that can be represented in an odd
560 * number of digits.
561 */
562 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000563
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100564 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000565 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100566 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000568 }
569
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100570 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200571 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000572
573 if( X->s == -1 )
574 *p++ = '-';
575
576 if( radix == 16 )
577 {
Paul Bakker23986e52011-04-24 08:57:21 +0000578 int c;
579 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000580
Paul Bakker23986e52011-04-24 08:57:21 +0000581 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000582 {
Paul Bakker23986e52011-04-24 08:57:21 +0000583 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000584 {
Paul Bakker23986e52011-04-24 08:57:21 +0000585 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000586
Paul Bakker6c343d72014-07-10 14:36:19 +0200587 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000588 continue;
589
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000590 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000591 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000592 k = 1;
593 }
594 }
595 }
596 else
597 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000599
600 if( T.s == -1 )
601 T.s = 1;
602
Ron Eldora16fa292018-11-20 14:07:01 +0200603 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000604 }
605
606 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100607 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000608
609cleanup:
610
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000612
613 return( ret );
614}
615
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200616#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000617/*
618 * Read X from an opened file
619 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000621{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000623 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000624 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000625 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000626 * Buffer should have space for (short) label and decimal formatted MPI,
627 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000628 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000630
631 memset( s, 0, sizeof( s ) );
632 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200633 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000634
635 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000636 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000638
Hanno Beckerb2034b72017-04-26 11:46:46 +0100639 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
640 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000641
642 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100643 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000644 if( mpi_get_digit( &d, radix, *p ) != 0 )
645 break;
646
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200647 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000648}
649
650/*
651 * Write X into an opened file (or stdout if fout == NULL)
652 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000654{
Paul Bakker23986e52011-04-24 08:57:21 +0000655 int ret;
656 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000657 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000658 * Buffer should have space for (short) label and decimal formatted MPI,
659 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000660 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000662
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100663 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000664
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100665 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000666
667 if( p == NULL ) p = "";
668
669 plen = strlen( p );
670 slen = strlen( s );
671 s[slen++] = '\r';
672 s[slen++] = '\n';
673
674 if( fout != NULL )
675 {
676 if( fwrite( p, 1, plen, fout ) != plen ||
677 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000679 }
680 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000682
683cleanup:
684
685 return( ret );
686}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000688
689/*
690 * Import X from unsigned binary data, big endian
691 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200692int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000693{
Paul Bakker23986e52011-04-24 08:57:21 +0000694 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100695 size_t i, j;
696 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000697
Hanno Becker073c1992017-10-17 15:17:27 +0100698 /* Ensure that target MPI has exactly the necessary number of limbs */
699 if( X->n != limbs )
700 {
701 mbedtls_mpi_free( X );
702 mbedtls_mpi_init( X );
703 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
704 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000705
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
Hanno Becker073c1992017-10-17 15:17:27 +0100708 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200709 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000710
711cleanup:
712
713 return( ret );
714}
715
716/*
717 * Export X into unsigned binary data, big endian
718 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000720{
Paul Bakker23986e52011-04-24 08:57:21 +0000721 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000722
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200723 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000724
725 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200726 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000727
728 memset( buf, 0, buflen );
729
730 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
731 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
732
733 return( 0 );
734}
735
736/*
737 * Left-shift: X <<= count
738 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000740{
Paul Bakker23986e52011-04-24 08:57:21 +0000741 int ret;
742 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000744
745 v0 = count / (biL );
746 t1 = count & (biL - 1);
747
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200748 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000749
Paul Bakkerf9688572011-05-05 10:00:45 +0000750 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200751 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000752
753 ret = 0;
754
755 /*
756 * shift by count / limb_size
757 */
758 if( v0 > 0 )
759 {
Paul Bakker23986e52011-04-24 08:57:21 +0000760 for( i = X->n; i > v0; i-- )
761 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000762
Paul Bakker23986e52011-04-24 08:57:21 +0000763 for( ; i > 0; i-- )
764 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000765 }
766
767 /*
768 * shift by count % limb_size
769 */
770 if( t1 > 0 )
771 {
772 for( i = v0; i < X->n; i++ )
773 {
774 r1 = X->p[i] >> (biL - t1);
775 X->p[i] <<= t1;
776 X->p[i] |= r0;
777 r0 = r1;
778 }
779 }
780
781cleanup:
782
783 return( ret );
784}
785
786/*
787 * Right-shift: X >>= count
788 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200789int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000790{
Paul Bakker23986e52011-04-24 08:57:21 +0000791 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200792 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000793
794 v0 = count / biL;
795 v1 = count & (biL - 1);
796
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100797 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200798 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100799
Paul Bakker5121ce52009-01-03 21:22:43 +0000800 /*
801 * shift by count / limb_size
802 */
803 if( v0 > 0 )
804 {
805 for( i = 0; i < X->n - v0; i++ )
806 X->p[i] = X->p[i + v0];
807
808 for( ; i < X->n; i++ )
809 X->p[i] = 0;
810 }
811
812 /*
813 * shift by count % limb_size
814 */
815 if( v1 > 0 )
816 {
Paul Bakker23986e52011-04-24 08:57:21 +0000817 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000818 {
Paul Bakker23986e52011-04-24 08:57:21 +0000819 r1 = X->p[i - 1] << (biL - v1);
820 X->p[i - 1] >>= v1;
821 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000822 r0 = r1;
823 }
824 }
825
826 return( 0 );
827}
828
829/*
830 * Compare unsigned values
831 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200832int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000833{
Paul Bakker23986e52011-04-24 08:57:21 +0000834 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000835
Paul Bakker23986e52011-04-24 08:57:21 +0000836 for( i = X->n; i > 0; i-- )
837 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000838 break;
839
Paul Bakker23986e52011-04-24 08:57:21 +0000840 for( j = Y->n; j > 0; j-- )
841 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000842 break;
843
Paul Bakker23986e52011-04-24 08:57:21 +0000844 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000845 return( 0 );
846
847 if( i > j ) return( 1 );
848 if( j > i ) return( -1 );
849
Paul Bakker23986e52011-04-24 08:57:21 +0000850 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000851 {
Paul Bakker23986e52011-04-24 08:57:21 +0000852 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
853 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000854 }
855
856 return( 0 );
857}
858
859/*
860 * Compare signed values
861 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200862int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000863{
Paul Bakker23986e52011-04-24 08:57:21 +0000864 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000865
Paul Bakker23986e52011-04-24 08:57:21 +0000866 for( i = X->n; i > 0; i-- )
867 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000868 break;
869
Paul Bakker23986e52011-04-24 08:57:21 +0000870 for( j = Y->n; j > 0; j-- )
871 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000872 break;
873
Paul Bakker23986e52011-04-24 08:57:21 +0000874 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000875 return( 0 );
876
877 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000878 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000879
880 if( X->s > 0 && Y->s < 0 ) return( 1 );
881 if( Y->s > 0 && X->s < 0 ) return( -1 );
882
Paul Bakker23986e52011-04-24 08:57:21 +0000883 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000884 {
Paul Bakker23986e52011-04-24 08:57:21 +0000885 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
886 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000887 }
888
889 return( 0 );
890}
891
892/*
893 * Compare signed values
894 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200895int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000896{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200897 mbedtls_mpi Y;
898 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000899
900 *p = ( z < 0 ) ? -z : z;
901 Y.s = ( z < 0 ) ? -1 : 1;
902 Y.n = 1;
903 Y.p = p;
904
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200905 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000906}
907
908/*
909 * Unsigned addition: X = |A| + |B| (HAC 14.7)
910 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200911int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000912{
Paul Bakker23986e52011-04-24 08:57:21 +0000913 int ret;
914 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100915 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000916
917 if( X == B )
918 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000920 }
921
922 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200923 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200924
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000925 /*
926 * X should always be positive as a result of unsigned additions.
927 */
928 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000929
Paul Bakker23986e52011-04-24 08:57:21 +0000930 for( j = B->n; j > 0; j-- )
931 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000932 break;
933
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200934 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000935
936 o = B->p; p = X->p; c = 0;
937
Janos Follath6c922682015-10-30 17:43:11 +0100938 /*
939 * tmp is used because it might happen that p == o
940 */
Paul Bakker23986e52011-04-24 08:57:21 +0000941 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000942 {
Janos Follath6c922682015-10-30 17:43:11 +0100943 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000944 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100945 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000946 }
947
948 while( c != 0 )
949 {
950 if( i >= X->n )
951 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200952 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000953 p = X->p + i;
954 }
955
Paul Bakker2d319fd2012-09-16 21:34:26 +0000956 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000957 }
958
959cleanup:
960
961 return( ret );
962}
963
964/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200965 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000966 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200967static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000968{
Paul Bakker23986e52011-04-24 08:57:21 +0000969 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200970 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000971
972 for( i = c = 0; i < n; i++, s++, d++ )
973 {
974 z = ( *d < c ); *d -= c;
975 c = ( *d < *s ) + z; *d -= *s;
976 }
977
978 while( c != 0 )
979 {
980 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +0200981 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000982 }
983}
984
985/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100986 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000987 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200988int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000989{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200990 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000991 int ret;
992 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000993
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200994 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
995 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000996
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200997 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000998
999 if( X == B )
1000 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001001 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001002 B = &TB;
1003 }
1004
1005 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001006 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001007
Paul Bakker1ef7a532009-06-20 10:50:55 +00001008 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001009 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001010 */
1011 X->s = 1;
1012
Paul Bakker5121ce52009-01-03 21:22:43 +00001013 ret = 0;
1014
Paul Bakker23986e52011-04-24 08:57:21 +00001015 for( n = B->n; n > 0; n-- )
1016 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001017 break;
1018
Paul Bakker23986e52011-04-24 08:57:21 +00001019 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001020
1021cleanup:
1022
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001023 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001024
1025 return( ret );
1026}
1027
1028/*
1029 * Signed addition: X = A + B
1030 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001031int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001032{
1033 int ret, s = A->s;
1034
1035 if( A->s * B->s < 0 )
1036 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001037 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001038 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001039 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001040 X->s = s;
1041 }
1042 else
1043 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001044 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001045 X->s = -s;
1046 }
1047 }
1048 else
1049 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001051 X->s = s;
1052 }
1053
1054cleanup:
1055
1056 return( ret );
1057}
1058
1059/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001060 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001061 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001062int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001063{
1064 int ret, s = A->s;
1065
1066 if( A->s * B->s > 0 )
1067 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001068 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001069 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001070 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001071 X->s = s;
1072 }
1073 else
1074 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001075 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001076 X->s = -s;
1077 }
1078 }
1079 else
1080 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001081 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001082 X->s = s;
1083 }
1084
1085cleanup:
1086
1087 return( ret );
1088}
1089
1090/*
1091 * Signed addition: X = A + b
1092 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001093int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001094{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001095 mbedtls_mpi _B;
1096 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001097
1098 p[0] = ( b < 0 ) ? -b : b;
1099 _B.s = ( b < 0 ) ? -1 : 1;
1100 _B.n = 1;
1101 _B.p = p;
1102
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001103 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001104}
1105
1106/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001107 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001108 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001109int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001110{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001111 mbedtls_mpi _B;
1112 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001113
1114 p[0] = ( b < 0 ) ? -b : b;
1115 _B.s = ( b < 0 ) ? -1 : 1;
1116 _B.n = 1;
1117 _B.p = p;
1118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001119 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001120}
1121
1122/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001123 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001124 */
1125static
1126#if defined(__APPLE__) && defined(__arm__)
1127/*
1128 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1129 * appears to need this to prevent bad ARM code generation at -O3.
1130 */
1131__attribute__ ((noinline))
1132#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001133void 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 +00001134{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001135 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001136
1137#if defined(MULADDC_HUIT)
1138 for( ; i >= 8; i -= 8 )
1139 {
1140 MULADDC_INIT
1141 MULADDC_HUIT
1142 MULADDC_STOP
1143 }
1144
1145 for( ; i > 0; i-- )
1146 {
1147 MULADDC_INIT
1148 MULADDC_CORE
1149 MULADDC_STOP
1150 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001151#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001152 for( ; i >= 16; i -= 16 )
1153 {
1154 MULADDC_INIT
1155 MULADDC_CORE MULADDC_CORE
1156 MULADDC_CORE MULADDC_CORE
1157 MULADDC_CORE MULADDC_CORE
1158 MULADDC_CORE MULADDC_CORE
1159
1160 MULADDC_CORE MULADDC_CORE
1161 MULADDC_CORE MULADDC_CORE
1162 MULADDC_CORE MULADDC_CORE
1163 MULADDC_CORE MULADDC_CORE
1164 MULADDC_STOP
1165 }
1166
1167 for( ; i >= 8; i -= 8 )
1168 {
1169 MULADDC_INIT
1170 MULADDC_CORE MULADDC_CORE
1171 MULADDC_CORE MULADDC_CORE
1172
1173 MULADDC_CORE MULADDC_CORE
1174 MULADDC_CORE MULADDC_CORE
1175 MULADDC_STOP
1176 }
1177
1178 for( ; i > 0; i-- )
1179 {
1180 MULADDC_INIT
1181 MULADDC_CORE
1182 MULADDC_STOP
1183 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001184#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001185
1186 t++;
1187
1188 do {
1189 *d += c; c = ( *d < c ); d++;
1190 }
1191 while( c != 0 );
1192}
1193
1194/*
1195 * Baseline multiplication: X = A * B (HAC 14.12)
1196 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001197int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001198{
Paul Bakker23986e52011-04-24 08:57:21 +00001199 int ret;
1200 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001201 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001202
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001203 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001204
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001205 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1206 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001207
Paul Bakker23986e52011-04-24 08:57:21 +00001208 for( i = A->n; i > 0; i-- )
1209 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001210 break;
1211
Paul Bakker23986e52011-04-24 08:57:21 +00001212 for( j = B->n; j > 0; j-- )
1213 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001214 break;
1215
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001216 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1217 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001218
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001219 for( ; j > 0; j-- )
1220 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001221
1222 X->s = A->s * B->s;
1223
1224cleanup:
1225
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001226 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001227
1228 return( ret );
1229}
1230
1231/*
1232 * Baseline multiplication: X = A * b
1233 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001234int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001235{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001236 mbedtls_mpi _B;
1237 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001238
1239 _B.s = 1;
1240 _B.n = 1;
1241 _B.p = p;
1242 p[0] = b;
1243
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001244 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001245}
1246
1247/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001248 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1249 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001250 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001251static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1252 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001253{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001254#if defined(MBEDTLS_HAVE_UDBL)
1255 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001256#else
Simon Butcher9803d072016-01-03 00:24:34 +00001257 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1258 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001259 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1260 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001261 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001262#endif
1263
Simon Butcher15b15d12015-11-26 19:35:03 +00001264 /*
1265 * Check for overflow
1266 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001267 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001268 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001269 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001270
Simon Butcherf5ba0452015-12-27 23:01:55 +00001271 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001272 }
1273
1274#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001275 dividend = (mbedtls_t_udbl) u1 << biL;
1276 dividend |= (mbedtls_t_udbl) u0;
1277 quotient = dividend / d;
1278 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1279 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1280
1281 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001282 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001283
1284 return (mbedtls_mpi_uint) quotient;
1285#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001286
1287 /*
1288 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1289 * Vol. 2 - Seminumerical Algorithms, Knuth
1290 */
1291
1292 /*
1293 * Normalize the divisor, d, and dividend, u0, u1
1294 */
1295 s = mbedtls_clz( d );
1296 d = d << s;
1297
1298 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001299 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001300 u0 = u0 << s;
1301
1302 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001303 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001304
1305 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001306 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001307
1308 /*
1309 * Find the first quotient and remainder
1310 */
1311 q1 = u1 / d1;
1312 r0 = u1 - d1 * q1;
1313
1314 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1315 {
1316 q1 -= 1;
1317 r0 += d1;
1318
1319 if ( r0 >= radix ) break;
1320 }
1321
Simon Butcherf5ba0452015-12-27 23:01:55 +00001322 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001323 q0 = rAX / d1;
1324 r0 = rAX - q0 * d1;
1325
1326 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1327 {
1328 q0 -= 1;
1329 r0 += d1;
1330
1331 if ( r0 >= radix ) break;
1332 }
1333
1334 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001335 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001336
1337 quotient = q1 * radix + q0;
1338
1339 return quotient;
1340#endif
1341}
1342
1343/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001344 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001345 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001346int 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 +00001347{
Paul Bakker23986e52011-04-24 08:57:21 +00001348 int ret;
1349 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001350 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001351
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001352 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1353 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001354
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001355 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1356 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001358 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001359 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001360 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1361 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001362 return( 0 );
1363 }
1364
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1366 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001367 X.s = Y.s = 1;
1368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001369 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1370 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1371 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1372 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001373
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001374 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001375 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001376 {
1377 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001378 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1379 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001380 }
1381 else k = 0;
1382
1383 n = X.n - 1;
1384 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001385 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001386
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001387 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001388 {
1389 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001391 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001393
1394 for( i = n; i > t ; i-- )
1395 {
1396 if( X.p[i] >= Y.p[t] )
1397 Z.p[i - t - 1] = ~0;
1398 else
1399 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001400 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1401 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001402 }
1403
1404 Z.p[i - t - 1]++;
1405 do
1406 {
1407 Z.p[i - t - 1]--;
1408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001409 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001410 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001411 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001412 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001413
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001415 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1416 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001417 T2.p[2] = X.p[i];
1418 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001419 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001420
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001421 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1422 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1423 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001424
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001425 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001426 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001427 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1428 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1429 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001430 Z.p[i - t - 1]--;
1431 }
1432 }
1433
1434 if( Q != NULL )
1435 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001436 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001437 Q->s = A->s * B->s;
1438 }
1439
1440 if( R != NULL )
1441 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001442 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001443 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001444 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001446 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001447 R->s = 1;
1448 }
1449
1450cleanup:
1451
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001452 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1453 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001454
1455 return( ret );
1456}
1457
1458/*
1459 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001460 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001461int 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 +00001462{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001463 mbedtls_mpi _B;
1464 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001465
1466 p[0] = ( b < 0 ) ? -b : b;
1467 _B.s = ( b < 0 ) ? -1 : 1;
1468 _B.n = 1;
1469 _B.p = p;
1470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001472}
1473
1474/*
1475 * Modulo: R = A mod B
1476 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001477int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001478{
1479 int ret;
1480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001481 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1482 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001484 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001485
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001486 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1487 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001489 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1490 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001491
1492cleanup:
1493
1494 return( ret );
1495}
1496
1497/*
1498 * Modulo: r = A mod b
1499 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001500int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001501{
Paul Bakker23986e52011-04-24 08:57:21 +00001502 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001503 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001504
1505 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001507
1508 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001509 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001510
1511 /*
1512 * handle trivial cases
1513 */
1514 if( b == 1 )
1515 {
1516 *r = 0;
1517 return( 0 );
1518 }
1519
1520 if( b == 2 )
1521 {
1522 *r = A->p[0] & 1;
1523 return( 0 );
1524 }
1525
1526 /*
1527 * general case
1528 */
Paul Bakker23986e52011-04-24 08:57:21 +00001529 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001530 {
Paul Bakker23986e52011-04-24 08:57:21 +00001531 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001532 y = ( y << biH ) | ( x >> biH );
1533 z = y / b;
1534 y -= z * b;
1535
1536 x <<= biH;
1537 y = ( y << biH ) | ( x >> biH );
1538 z = y / b;
1539 y -= z * b;
1540 }
1541
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001542 /*
1543 * If A is negative, then the current y represents a negative value.
1544 * Flipping it to the positive side.
1545 */
1546 if( A->s < 0 && y != 0 )
1547 y = b - y;
1548
Paul Bakker5121ce52009-01-03 21:22:43 +00001549 *r = y;
1550
1551 return( 0 );
1552}
1553
1554/*
1555 * Fast Montgomery initialization (thanks to Tom St Denis)
1556 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001557static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001558{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001559 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001560 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001561
1562 x = m0;
1563 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001564
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001565 for( i = biL; i >= 8; i /= 2 )
1566 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001567
1568 *mm = ~x + 1;
1569}
1570
1571/*
1572 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1573 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001574static int 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 +02001575 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001576{
Paul Bakker23986e52011-04-24 08:57:21 +00001577 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001578 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001579
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001580 if( T->n < N->n + 1 || T->p == NULL )
1581 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1582
Paul Bakker5121ce52009-01-03 21:22:43 +00001583 memset( T->p, 0, T->n * ciL );
1584
1585 d = T->p;
1586 n = N->n;
1587 m = ( B->n < n ) ? B->n : n;
1588
1589 for( i = 0; i < n; i++ )
1590 {
1591 /*
1592 * T = (T + u0*B + u1*N) / 2^biL
1593 */
1594 u0 = A->p[i];
1595 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1596
1597 mpi_mul_hlp( m, B->p, d, u0 );
1598 mpi_mul_hlp( n, N->p, d, u1 );
1599
1600 *d++ = u0; d[n + 1] = 0;
1601 }
1602
Paul Bakker66d5d072014-06-17 16:39:18 +02001603 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001604
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001605 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001606 mpi_sub_hlp( n, N->p, A->p );
1607 else
1608 /* prevent timing attacks */
1609 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001610
1611 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001612}
1613
1614/*
1615 * Montgomery reduction: A = A * R^-1 mod N
1616 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001617static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001618{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001619 mbedtls_mpi_uint z = 1;
1620 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001621
Paul Bakker8ddb6452013-02-27 14:56:33 +01001622 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001623 U.p = &z;
1624
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001625 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001626}
1627
1628/*
1629 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1630 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001631int 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 +00001632{
Paul Bakker23986e52011-04-24 08:57:21 +00001633 int ret;
1634 size_t wbits, wsize, one = 1;
1635 size_t i, j, nblimbs;
1636 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001637 mbedtls_mpi_uint ei, mm, state;
1638 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001639 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001640
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001641 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001642 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001643
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001644 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1645 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001646
1647 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001648 * Init temps and window size
1649 */
1650 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1652 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001653 memset( W, 0, sizeof( W ) );
1654
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001655 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001656
1657 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1658 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1659
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001660 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1661 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001662
Paul Bakker5121ce52009-01-03 21:22:43 +00001663 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001664 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1665 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1666 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001667
1668 /*
Paul Bakker50546922012-05-19 08:40:49 +00001669 * Compensate for negative A (and correct at the end)
1670 */
1671 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001672 if( neg )
1673 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001674 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001675 Apos.s = 1;
1676 A = &Apos;
1677 }
1678
1679 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001680 * If 1st call, pre-compute R^2 mod N
1681 */
1682 if( _RR == NULL || _RR->p == NULL )
1683 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001684 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1685 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1686 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001687
1688 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001689 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001690 }
1691 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001692 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001693
1694 /*
1695 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1696 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001697 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1698 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001699 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001700 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001701
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001702 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001703
1704 /*
1705 * X = R^2 * R^-1 mod N = R mod N
1706 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001707 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001708 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001709
1710 if( wsize > 1 )
1711 {
1712 /*
1713 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1714 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001715 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001716
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001717 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1718 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001719
1720 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001721 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001722
Paul Bakker5121ce52009-01-03 21:22:43 +00001723 /*
1724 * W[i] = W[i - 1] * W[1]
1725 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001726 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001727 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001728 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1729 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001730
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001731 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001732 }
1733 }
1734
1735 nblimbs = E->n;
1736 bufsize = 0;
1737 nbits = 0;
1738 wbits = 0;
1739 state = 0;
1740
1741 while( 1 )
1742 {
1743 if( bufsize == 0 )
1744 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001745 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001746 break;
1747
Paul Bakker0d7702c2013-10-29 16:18:35 +01001748 nblimbs--;
1749
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001750 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001751 }
1752
1753 bufsize--;
1754
1755 ei = (E->p[nblimbs] >> bufsize) & 1;
1756
1757 /*
1758 * skip leading 0s
1759 */
1760 if( ei == 0 && state == 0 )
1761 continue;
1762
1763 if( ei == 0 && state == 1 )
1764 {
1765 /*
1766 * out of window, square X
1767 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001768 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001769 continue;
1770 }
1771
1772 /*
1773 * add ei to current window
1774 */
1775 state = 2;
1776
1777 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001778 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001779
1780 if( nbits == wsize )
1781 {
1782 /*
1783 * X = X^wsize R^-1 mod N
1784 */
1785 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001786 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001787
1788 /*
1789 * X = X * W[wbits] R^-1 mod N
1790 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001791 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001792
1793 state--;
1794 nbits = 0;
1795 wbits = 0;
1796 }
1797 }
1798
1799 /*
1800 * process the remaining bits
1801 */
1802 for( i = 0; i < nbits; i++ )
1803 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001804 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001805
1806 wbits <<= 1;
1807
Paul Bakker66d5d072014-06-17 16:39:18 +02001808 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001809 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001810 }
1811
1812 /*
1813 * X = A^E * R * R^-1 mod N = A^E mod N
1814 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001815 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001816
Hanno Beckera4af1c42017-04-18 09:07:45 +01001817 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001818 {
1819 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001820 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001821 }
1822
Paul Bakker5121ce52009-01-03 21:22:43 +00001823cleanup:
1824
Paul Bakker66d5d072014-06-17 16:39:18 +02001825 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001826 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001827
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001828 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001829
Paul Bakker75a28602014-03-31 12:08:17 +02001830 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001831 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001832
1833 return( ret );
1834}
1835
Paul Bakker5121ce52009-01-03 21:22:43 +00001836/*
1837 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1838 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001839int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001840{
Paul Bakker23986e52011-04-24 08:57:21 +00001841 int ret;
1842 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001843 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001844
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001845 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001847 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1848 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001849
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001850 lz = mbedtls_mpi_lsb( &TA );
1851 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001852
Paul Bakker66d5d072014-06-17 16:39:18 +02001853 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001854 lz = lzt;
1855
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001856 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1857 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001858
Paul Bakker5121ce52009-01-03 21:22:43 +00001859 TA.s = TB.s = 1;
1860
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001861 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001862 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001863 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1864 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001865
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001866 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001867 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001868 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1869 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001870 }
1871 else
1872 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001873 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1874 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001875 }
1876 }
1877
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001878 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1879 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001880
1881cleanup:
1882
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001883 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001884
1885 return( ret );
1886}
1887
Paul Bakker33dc46b2014-04-30 16:11:39 +02001888/*
1889 * Fill X with size bytes of random.
1890 *
1891 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001892 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001893 * deterministic, eg for tests).
1894 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001895int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001896 int (*f_rng)(void *, unsigned char *, size_t),
1897 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001898{
Paul Bakker23986e52011-04-24 08:57:21 +00001899 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001900 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001901
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001902 if( size > MBEDTLS_MPI_MAX_SIZE )
1903 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001904
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001905 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1906 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001907
1908cleanup:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -05001909 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001910 return( ret );
1911}
1912
Paul Bakker5121ce52009-01-03 21:22:43 +00001913/*
1914 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1915 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001916int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001917{
1918 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001919 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001920
Hanno Becker4bcb4912017-04-18 15:49:39 +01001921 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001922 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001923
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001924 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1925 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1926 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001927
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001928 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001929
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001930 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001931 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001932 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001933 goto cleanup;
1934 }
1935
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001936 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1937 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1938 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1939 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001940
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001941 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1942 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1943 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1944 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
1946 do
1947 {
1948 while( ( TU.p[0] & 1 ) == 0 )
1949 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001950 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001951
1952 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1953 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001954 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1955 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956 }
1957
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001958 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1959 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001960 }
1961
1962 while( ( TV.p[0] & 1 ) == 0 )
1963 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001964 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001965
1966 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1967 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001968 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1969 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001970 }
1971
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001972 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1973 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001974 }
1975
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001976 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001977 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001978 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1979 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1980 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001981 }
1982 else
1983 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001984 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1985 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1986 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001987 }
1988 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001989 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001990
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001991 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1992 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001993
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001994 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1995 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001996
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001997 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001998
1999cleanup:
2000
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002001 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2002 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2003 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002004
2005 return( ret );
2006}
2007
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002008#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002009
Paul Bakker5121ce52009-01-03 21:22:43 +00002010static const int small_prime[] =
2011{
2012 3, 5, 7, 11, 13, 17, 19, 23,
2013 29, 31, 37, 41, 43, 47, 53, 59,
2014 61, 67, 71, 73, 79, 83, 89, 97,
2015 101, 103, 107, 109, 113, 127, 131, 137,
2016 139, 149, 151, 157, 163, 167, 173, 179,
2017 181, 191, 193, 197, 199, 211, 223, 227,
2018 229, 233, 239, 241, 251, 257, 263, 269,
2019 271, 277, 281, 283, 293, 307, 311, 313,
2020 317, 331, 337, 347, 349, 353, 359, 367,
2021 373, 379, 383, 389, 397, 401, 409, 419,
2022 421, 431, 433, 439, 443, 449, 457, 461,
2023 463, 467, 479, 487, 491, 499, 503, 509,
2024 521, 523, 541, 547, 557, 563, 569, 571,
2025 577, 587, 593, 599, 601, 607, 613, 617,
2026 619, 631, 641, 643, 647, 653, 659, 661,
2027 673, 677, 683, 691, 701, 709, 719, 727,
2028 733, 739, 743, 751, 757, 761, 769, 773,
2029 787, 797, 809, 811, 821, 823, 827, 829,
2030 839, 853, 857, 859, 863, 877, 881, 883,
2031 887, 907, 911, 919, 929, 937, 941, 947,
2032 953, 967, 971, 977, 983, 991, 997, -103
2033};
2034
2035/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002036 * Small divisors test (X must be positive)
2037 *
2038 * Return values:
2039 * 0: no small factor (possible prime, more tests needed)
2040 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002041 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002042 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002043 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002044static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002045{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002046 int ret = 0;
2047 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002048 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002049
Paul Bakker5121ce52009-01-03 21:22:43 +00002050 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002051 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002052
2053 for( i = 0; small_prime[i] > 0; i++ )
2054 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002055 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002056 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002057
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002059
2060 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002061 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002062 }
2063
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002064cleanup:
2065 return( ret );
2066}
2067
2068/*
2069 * Miller-Rabin pseudo-primality test (HAC 4.24)
2070 */
Janos Follathda31fa12018-09-03 14:45:23 +01002071static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002072 int (*f_rng)(void *, unsigned char *, size_t),
2073 void *p_rng )
2074{
Pascal Junodb99183d2015-03-11 16:49:45 +01002075 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002076 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002077 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002078
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002079 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2080 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002081
Paul Bakker5121ce52009-01-03 21:22:43 +00002082 /*
2083 * W = |X| - 1
2084 * R = W >> lsb( W )
2085 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002086 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2087 s = mbedtls_mpi_lsb( &W );
2088 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2089 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002090
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002091 i = mbedtls_mpi_bitlen( X );
Janos Follathf301d232018-08-14 13:34:01 +01002092
Janos Follathda31fa12018-09-03 14:45:23 +01002093 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002094 {
2095 /*
2096 * pick a random A, 1 < A < |X| - 1
2097 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002098 count = 0;
2099 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002100 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002101
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002102 j = mbedtls_mpi_bitlen( &A );
2103 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002104 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002105 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002106 }
2107
2108 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002109 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002110 }
2111
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002112 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2113 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002114
2115 /*
2116 * A = A^R mod |X|
2117 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002118 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002120 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2121 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002122 continue;
2123
2124 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002125 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002126 {
2127 /*
2128 * A = A * A mod |X|
2129 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002130 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2131 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002132
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002133 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002134 break;
2135
2136 j++;
2137 }
2138
2139 /*
2140 * not prime if A != |X| - 1 or A == 1
2141 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002142 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2143 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002144 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002146 break;
2147 }
2148 }
2149
2150cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002151 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2152 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002153
2154 return( ret );
2155}
2156
2157/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002158 * Pseudo-primality test: small factors, then Miller-Rabin
2159 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002160int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2161 int (*f_rng)(void *, unsigned char *, size_t),
2162 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002163{
2164 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002165 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002166
2167 XX.s = 1;
2168 XX.n = X->n;
2169 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002170
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002171 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2172 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2173 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002174
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002175 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002176 return( 0 );
2177
2178 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2179 {
2180 if( ret == 1 )
2181 return( 0 );
2182
2183 return( ret );
2184 }
2185
Janos Follathda31fa12018-09-03 14:45:23 +01002186 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002187}
2188
Janos Follatha0b67c22018-09-18 14:48:23 +01002189#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002190/*
2191 * Pseudo-primality test, error probability 2^-80
2192 */
2193int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2194 int (*f_rng)(void *, unsigned char *, size_t),
2195 void *p_rng )
2196{
Janos Follatha0b67c22018-09-18 14:48:23 +01002197 /*
2198 * In the past our key generation aimed for an error rate of at most
2199 * 2^-80. Since this function is deprecated, aim for the same certainty
2200 * here as well.
2201 */
2202 return mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002203}
Janos Follatha0b67c22018-09-18 14:48:23 +01002204#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002205
2206/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002207 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002208 *
Janos Follathf301d232018-08-14 13:34:01 +01002209 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2210 * be either 1024 bits or 1536 bits long, and flags must contain
2211 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002212 */
Janos Follath7c025a92018-08-14 11:08:41 +01002213int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002214 int (*f_rng)(void *, unsigned char *, size_t),
2215 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002216{
Jethro Beekman66689272018-02-14 19:24:10 -08002217#ifdef MBEDTLS_HAVE_INT64
2218// ceil(2^63.5)
2219#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2220#else
2221// ceil(2^31.5)
2222#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2223#endif
2224 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002225 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002226 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002227 mbedtls_mpi_uint r;
2228 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002229
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002230 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2231 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002232
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002233 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002234
2235 n = BITS_TO_LIMBS( nbits );
2236
Janos Follathda31fa12018-09-03 14:45:23 +01002237 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2238 {
2239 /*
2240 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2241 */
2242 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2243 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2244 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2245 }
2246 else
2247 {
2248 /*
2249 * 2^-100 error probability, number of rounds computed based on HAC,
2250 * fact 4.48
2251 */
2252 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2253 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2254 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2255 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2256 }
2257
Jethro Beekman66689272018-02-14 19:24:10 -08002258 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002259 {
Jethro Beekman66689272018-02-14 19:24:10 -08002260 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2261 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2262 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2263
2264 k = n * biL;
2265 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2266 X->p[0] |= 1;
2267
Janos Follath7c025a92018-08-14 11:08:41 +01002268 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002269 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002270 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002271
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002273 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002274 }
Jethro Beekman66689272018-02-14 19:24:10 -08002275 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002276 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002277 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002278 * An necessary condition for Y and X = 2Y + 1 to be prime
2279 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2280 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002281 */
Jethro Beekman66689272018-02-14 19:24:10 -08002282
2283 X->p[0] |= 2;
2284
2285 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2286 if( r == 0 )
2287 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2288 else if( r == 1 )
2289 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2290
2291 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2292 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2293 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2294
2295 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002296 {
Jethro Beekman66689272018-02-14 19:24:10 -08002297 /*
2298 * First, check small factors for X and Y
2299 * before doing Miller-Rabin on any of them
2300 */
2301 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2302 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002303 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002304 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002305 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002306 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002307 goto cleanup;
2308
2309 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2310 goto cleanup;
2311
2312 /*
2313 * Next candidates. We want to preserve Y = (X-1) / 2 and
2314 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2315 * so up Y by 6 and X by 12.
2316 */
2317 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2318 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002319 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002320 }
2321 }
2322
2323cleanup:
2324
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002325 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002326
2327 return( ret );
2328}
2329
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002332#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002333
Paul Bakker23986e52011-04-24 08:57:21 +00002334#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002335
2336static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2337{
2338 { 693, 609, 21 },
2339 { 1764, 868, 28 },
2340 { 768454923, 542167814, 1 }
2341};
2342
Paul Bakker5121ce52009-01-03 21:22:43 +00002343/*
2344 * Checkup routine
2345 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002346int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002347{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002348 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002349 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002350
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002351 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2352 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002354 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002355 "EFE021C2645FD1DC586E69184AF4A31E" \
2356 "D5F53E93B5F123FA41680867BA110131" \
2357 "944FE7952E2517337780CB0DB80E61AA" \
2358 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2359
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002360 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002361 "B2E7EFD37075B9F03FF989C7C5051C20" \
2362 "34D2A323810251127E7BF8625A4F49A5" \
2363 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2364 "5B5C25763222FEFCCFC38B832366C29E" ) );
2365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002366 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002367 "0066A198186C18C10B2F5ED9B522752A" \
2368 "9830B69916E535C8F047518A889A43A5" \
2369 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2370
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002371 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002372
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002373 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002374 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2375 "9E857EA95A03512E2BAE7391688D264A" \
2376 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2377 "8001B72E848A38CAE1C65F78E56ABDEF" \
2378 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2379 "ECF677152EF804370C1A305CAF3B5BF1" \
2380 "30879B56C61DE584A0F53A2447A51E" ) );
2381
2382 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002386 {
2387 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002388 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002389
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002390 ret = 1;
2391 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002392 }
2393
2394 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002395 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002397 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002398
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002399 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002400 "256567336059E52CAE22925474705F39A94" ) );
2401
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002402 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002403 "6613F26162223DF488E9CD48CC132C7A" \
2404 "0AC93C701B001B092E4E5B9F73BCD27B" \
2405 "9EE50D0657C77F374E903CDFA4C642" ) );
2406
2407 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002408 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002409
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002410 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2411 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002412 {
2413 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002414 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002415
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002416 ret = 1;
2417 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002418 }
2419
2420 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002421 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002422
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002423 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002424
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002425 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002426 "36E139AEA55215609D2816998ED020BB" \
2427 "BD96C37890F65171D948E9BC7CBAA4D9" \
2428 "325D24D6A3C12710F10A09FA08AB87" ) );
2429
2430 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002431 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002432
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002433 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002434 {
2435 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002436 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002437
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002438 ret = 1;
2439 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002440 }
2441
2442 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002443 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002445 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002446
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002447 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002448 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2449 "C3DBA76456363A10869622EAC2DD84EC" \
2450 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2451
2452 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002453 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002455 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002456 {
2457 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002458 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002459
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002460 ret = 1;
2461 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002462 }
2463
2464 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002465 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002466
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002467 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002468 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002469
Paul Bakker66d5d072014-06-17 16:39:18 +02002470 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002471 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002472 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2473 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002474
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002476
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002477 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002478 {
2479 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002480 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002481
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002482 ret = 1;
2483 goto cleanup;
2484 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002485 }
2486
2487 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002488 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002489
Paul Bakker5121ce52009-01-03 21:22:43 +00002490cleanup:
2491
2492 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002493 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002494
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002495 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2496 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002497
2498 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002499 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002500
2501 return( ret );
2502}
2503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002504#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002505
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002506#endif /* MBEDTLS_BIGNUM_C */