blob: be4df2fe78ee77042e5b3d0d6f4399f4d36959aa [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
Gilles Peskine11cdb052018-11-20 16:47:47 +0100324/* Get a specific byte, without range checks. */
325#define GET_BYTE( X, i ) \
326 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
327
Paul Bakker2f5947e2011-05-18 15:47:11 +0000328/*
329 * Set a bit to a specific value of 0 or 1
330 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200331int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332{
333 int ret = 0;
334 size_t off = pos / biL;
335 size_t idx = pos % biL;
336
337 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200338 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200339
Paul Bakker2f5947e2011-05-18 15:47:11 +0000340 if( X->n * biL <= pos )
341 {
342 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200343 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200345 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000346 }
347
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200348 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
349 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000350
351cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200352
Paul Bakker2f5947e2011-05-18 15:47:11 +0000353 return( ret );
354}
355
356/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200357 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000358 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000360{
Paul Bakker23986e52011-04-24 08:57:21 +0000361 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000362
363 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000364 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000365 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
366 return( count );
367
368 return( 0 );
369}
370
371/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000372 * Count leading zero bits in a given integer
373 */
374static size_t mbedtls_clz( const mbedtls_mpi_uint x )
375{
376 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100377 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000378
379 for( j = 0; j < biL; j++ )
380 {
381 if( x & mask ) break;
382
383 mask >>= 1;
384 }
385
386 return j;
387}
388
389/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200390 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000391 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200392size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000393{
Paul Bakker23986e52011-04-24 08:57:21 +0000394 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000395
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200396 if( X->n == 0 )
397 return( 0 );
398
Paul Bakker5121ce52009-01-03 21:22:43 +0000399 for( i = X->n - 1; i > 0; i-- )
400 if( X->p[i] != 0 )
401 break;
402
Simon Butcher15b15d12015-11-26 19:35:03 +0000403 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000404
Paul Bakker23986e52011-04-24 08:57:21 +0000405 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000406}
407
408/*
409 * Return the total size in bytes
410 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200411size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000412{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200413 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000414}
415
416/*
417 * Convert an ASCII character to digit value
418 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000420{
421 *d = 255;
422
423 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
424 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
425 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
426
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200427 if( *d >= (mbedtls_mpi_uint) radix )
428 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000429
430 return( 0 );
431}
432
433/*
434 * Import from an ASCII string
435 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200436int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000437{
Paul Bakker23986e52011-04-24 08:57:21 +0000438 int ret;
439 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200440 mbedtls_mpi_uint d;
441 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
443 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200444 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000447
Paul Bakkerff60ee62010-03-16 21:09:09 +0000448 slen = strlen( s );
449
Paul Bakker5121ce52009-01-03 21:22:43 +0000450 if( radix == 16 )
451 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100452 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200453 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
454
Paul Bakkerff60ee62010-03-16 21:09:09 +0000455 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
458 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000459
Paul Bakker23986e52011-04-24 08:57:21 +0000460 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000461 {
Paul Bakker23986e52011-04-24 08:57:21 +0000462 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000463 {
464 X->s = -1;
465 break;
466 }
467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200468 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200469 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000470 }
471 }
472 else
473 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000475
Paul Bakkerff60ee62010-03-16 21:09:09 +0000476 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000477 {
478 if( i == 0 && s[i] == '-' )
479 {
480 X->s = -1;
481 continue;
482 }
483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
485 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000486
487 if( X->s == 1 )
488 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000490 }
491 else
492 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000494 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000495 }
496 }
497
498cleanup:
499
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200500 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000501
502 return( ret );
503}
504
505/*
506 * Helper to write the digits high-order first
507 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000509{
510 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200511 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000512
513 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000515
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
517 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000518
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
520 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000521
522 if( r < 10 )
523 *(*p)++ = (char)( r + 0x30 );
524 else
525 *(*p)++ = (char)( r + 0x37 );
526
527cleanup:
528
529 return( ret );
530}
531
532/*
533 * Export into an ASCII string
534 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100535int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
536 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000537{
Paul Bakker23986e52011-04-24 08:57:21 +0000538 int ret = 0;
539 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000540 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200541 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000542
543 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200544 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000545
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200546 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000547 if( radix >= 4 ) n >>= 1;
548 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000549 /*
550 * Round up the buffer length to an even value to ensure that there is
551 * enough room for hexadecimal values that can be represented in an odd
552 * number of digits.
553 */
554 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000555
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100556 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000557 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100558 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200559 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000560 }
561
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100562 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200563 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000564
565 if( X->s == -1 )
566 *p++ = '-';
567
568 if( radix == 16 )
569 {
Paul Bakker23986e52011-04-24 08:57:21 +0000570 int c;
571 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000572
Paul Bakker23986e52011-04-24 08:57:21 +0000573 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000574 {
Paul Bakker23986e52011-04-24 08:57:21 +0000575 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000576 {
Paul Bakker23986e52011-04-24 08:57:21 +0000577 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000578
Paul Bakker6c343d72014-07-10 14:36:19 +0200579 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000580 continue;
581
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000582 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000583 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000584 k = 1;
585 }
586 }
587 }
588 else
589 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200590 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000591
592 if( T.s == -1 )
593 T.s = 1;
594
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200595 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000596 }
597
598 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100599 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000600
601cleanup:
602
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000604
605 return( ret );
606}
607
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000609/*
610 * Read X from an opened file
611 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000613{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200614 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000615 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000616 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000617 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000618 * Buffer should have space for (short) label and decimal formatted MPI,
619 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000620 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000622
623 memset( s, 0, sizeof( s ) );
624 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200625 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000626
627 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000628 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000630
Hanno Beckerb2034b72017-04-26 11:46:46 +0100631 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
632 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000633
634 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100635 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000636 if( mpi_get_digit( &d, radix, *p ) != 0 )
637 break;
638
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200639 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000640}
641
642/*
643 * Write X into an opened file (or stdout if fout == NULL)
644 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200645int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000646{
Paul Bakker23986e52011-04-24 08:57:21 +0000647 int ret;
648 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000649 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000650 * Buffer should have space for (short) label and decimal formatted MPI,
651 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000652 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000654
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100655 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000656
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100657 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000658
659 if( p == NULL ) p = "";
660
661 plen = strlen( p );
662 slen = strlen( s );
663 s[slen++] = '\r';
664 s[slen++] = '\n';
665
666 if( fout != NULL )
667 {
668 if( fwrite( p, 1, plen, fout ) != plen ||
669 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000671 }
672 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200673 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000674
675cleanup:
676
677 return( ret );
678}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200679#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000680
681/*
682 * Import X from unsigned binary data, big endian
683 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000685{
Paul Bakker23986e52011-04-24 08:57:21 +0000686 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100687 size_t i, j;
688 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000689
Hanno Becker073c1992017-10-17 15:17:27 +0100690 /* Ensure that target MPI has exactly the necessary number of limbs */
691 if( X->n != limbs )
692 {
693 mbedtls_mpi_free( X );
694 mbedtls_mpi_init( X );
695 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
696 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000697
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000699
Hanno Becker073c1992017-10-17 15:17:27 +0100700 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000702
703cleanup:
704
705 return( ret );
706}
707
708/*
709 * Export X into unsigned binary data, big endian
710 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100711int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
712 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000713{
Gilles Peskine11cdb052018-11-20 16:47:47 +0100714 size_t stored_bytes = X->n * ciL;
715 size_t bytes_to_copy;
716 unsigned char *p;
717 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000718
Gilles Peskine11cdb052018-11-20 16:47:47 +0100719 if( stored_bytes < buflen )
720 {
721 /* There is enough space in the output buffer. Write initial
722 * null bytes and record the position at which to start
723 * writing the significant bytes. In this case, the execution
724 * trace of this function does not depend on the value of the
725 * number. */
726 bytes_to_copy = stored_bytes;
727 p = buf + buflen - stored_bytes;
728 memset( buf, 0, buflen - stored_bytes );
729 }
730 else
731 {
732 /* The output buffer is smaller than the allocated size of X.
733 * However X may fit if its leading bytes are zero. */
734 bytes_to_copy = buflen;
735 p = buf;
736 for( i = bytes_to_copy; i < stored_bytes; i++ )
737 {
738 if( GET_BYTE( X, i ) != 0 )
739 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
740 }
741 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000742
Gilles Peskine11cdb052018-11-20 16:47:47 +0100743 for( i = 0; i < bytes_to_copy; i++ )
744 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000745
746 return( 0 );
747}
748
749/*
750 * Left-shift: X <<= count
751 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200752int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000753{
Paul Bakker23986e52011-04-24 08:57:21 +0000754 int ret;
755 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200756 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000757
758 v0 = count / (biL );
759 t1 = count & (biL - 1);
760
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200761 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000762
Paul Bakkerf9688572011-05-05 10:00:45 +0000763 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200764 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000765
766 ret = 0;
767
768 /*
769 * shift by count / limb_size
770 */
771 if( v0 > 0 )
772 {
Paul Bakker23986e52011-04-24 08:57:21 +0000773 for( i = X->n; i > v0; i-- )
774 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000775
Paul Bakker23986e52011-04-24 08:57:21 +0000776 for( ; i > 0; i-- )
777 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000778 }
779
780 /*
781 * shift by count % limb_size
782 */
783 if( t1 > 0 )
784 {
785 for( i = v0; i < X->n; i++ )
786 {
787 r1 = X->p[i] >> (biL - t1);
788 X->p[i] <<= t1;
789 X->p[i] |= r0;
790 r0 = r1;
791 }
792 }
793
794cleanup:
795
796 return( ret );
797}
798
799/*
800 * Right-shift: X >>= count
801 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200802int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000803{
Paul Bakker23986e52011-04-24 08:57:21 +0000804 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200805 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000806
807 v0 = count / biL;
808 v1 = count & (biL - 1);
809
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100810 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200811 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100812
Paul Bakker5121ce52009-01-03 21:22:43 +0000813 /*
814 * shift by count / limb_size
815 */
816 if( v0 > 0 )
817 {
818 for( i = 0; i < X->n - v0; i++ )
819 X->p[i] = X->p[i + v0];
820
821 for( ; i < X->n; i++ )
822 X->p[i] = 0;
823 }
824
825 /*
826 * shift by count % limb_size
827 */
828 if( v1 > 0 )
829 {
Paul Bakker23986e52011-04-24 08:57:21 +0000830 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000831 {
Paul Bakker23986e52011-04-24 08:57:21 +0000832 r1 = X->p[i - 1] << (biL - v1);
833 X->p[i - 1] >>= v1;
834 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000835 r0 = r1;
836 }
837 }
838
839 return( 0 );
840}
841
842/*
843 * Compare unsigned values
844 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200845int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000846{
Paul Bakker23986e52011-04-24 08:57:21 +0000847 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000848
Paul Bakker23986e52011-04-24 08:57:21 +0000849 for( i = X->n; i > 0; i-- )
850 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000851 break;
852
Paul Bakker23986e52011-04-24 08:57:21 +0000853 for( j = Y->n; j > 0; j-- )
854 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000855 break;
856
Paul Bakker23986e52011-04-24 08:57:21 +0000857 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000858 return( 0 );
859
860 if( i > j ) return( 1 );
861 if( j > i ) return( -1 );
862
Paul Bakker23986e52011-04-24 08:57:21 +0000863 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000864 {
Paul Bakker23986e52011-04-24 08:57:21 +0000865 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
866 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000867 }
868
869 return( 0 );
870}
871
872/*
873 * Compare signed values
874 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200875int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000876{
Paul Bakker23986e52011-04-24 08:57:21 +0000877 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000878
Paul Bakker23986e52011-04-24 08:57:21 +0000879 for( i = X->n; i > 0; i-- )
880 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000881 break;
882
Paul Bakker23986e52011-04-24 08:57:21 +0000883 for( j = Y->n; j > 0; j-- )
884 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000885 break;
886
Paul Bakker23986e52011-04-24 08:57:21 +0000887 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000888 return( 0 );
889
890 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000891 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000892
893 if( X->s > 0 && Y->s < 0 ) return( 1 );
894 if( Y->s > 0 && X->s < 0 ) return( -1 );
895
Paul Bakker23986e52011-04-24 08:57:21 +0000896 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000897 {
Paul Bakker23986e52011-04-24 08:57:21 +0000898 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
899 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000900 }
901
902 return( 0 );
903}
904
905/*
906 * Compare signed values
907 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200908int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000909{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200910 mbedtls_mpi Y;
911 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000912
913 *p = ( z < 0 ) ? -z : z;
914 Y.s = ( z < 0 ) ? -1 : 1;
915 Y.n = 1;
916 Y.p = p;
917
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200918 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000919}
920
921/*
922 * Unsigned addition: X = |A| + |B| (HAC 14.7)
923 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200924int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000925{
Paul Bakker23986e52011-04-24 08:57:21 +0000926 int ret;
927 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100928 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000929
930 if( X == B )
931 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200932 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000933 }
934
935 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200936 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200937
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000938 /*
939 * X should always be positive as a result of unsigned additions.
940 */
941 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000942
Paul Bakker23986e52011-04-24 08:57:21 +0000943 for( j = B->n; j > 0; j-- )
944 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000945 break;
946
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000948
949 o = B->p; p = X->p; c = 0;
950
Janos Follath6c922682015-10-30 17:43:11 +0100951 /*
952 * tmp is used because it might happen that p == o
953 */
Paul Bakker23986e52011-04-24 08:57:21 +0000954 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000955 {
Janos Follath6c922682015-10-30 17:43:11 +0100956 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000957 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100958 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000959 }
960
961 while( c != 0 )
962 {
963 if( i >= X->n )
964 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200965 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000966 p = X->p + i;
967 }
968
Paul Bakker2d319fd2012-09-16 21:34:26 +0000969 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000970 }
971
972cleanup:
973
974 return( ret );
975}
976
977/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200978 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000979 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200980static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000981{
Paul Bakker23986e52011-04-24 08:57:21 +0000982 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200983 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000984
985 for( i = c = 0; i < n; i++, s++, d++ )
986 {
987 z = ( *d < c ); *d -= c;
988 c = ( *d < *s ) + z; *d -= *s;
989 }
990
991 while( c != 0 )
992 {
993 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +0200994 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000995 }
996}
997
998/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100999 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001000 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001001int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001002{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001003 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001004 int ret;
1005 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001006
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001007 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1008 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001009
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001010 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001011
1012 if( X == B )
1013 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001014 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001015 B = &TB;
1016 }
1017
1018 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001020
Paul Bakker1ef7a532009-06-20 10:50:55 +00001021 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001022 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001023 */
1024 X->s = 1;
1025
Paul Bakker5121ce52009-01-03 21:22:43 +00001026 ret = 0;
1027
Paul Bakker23986e52011-04-24 08:57:21 +00001028 for( n = B->n; n > 0; n-- )
1029 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001030 break;
1031
Paul Bakker23986e52011-04-24 08:57:21 +00001032 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001033
1034cleanup:
1035
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001036 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001037
1038 return( ret );
1039}
1040
1041/*
1042 * Signed addition: X = A + B
1043 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001044int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001045{
1046 int ret, s = A->s;
1047
1048 if( A->s * B->s < 0 )
1049 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001051 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001052 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001053 X->s = s;
1054 }
1055 else
1056 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001057 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001058 X->s = -s;
1059 }
1060 }
1061 else
1062 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001063 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001064 X->s = s;
1065 }
1066
1067cleanup:
1068
1069 return( ret );
1070}
1071
1072/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001073 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001074 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001075int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001076{
1077 int ret, s = A->s;
1078
1079 if( A->s * B->s > 0 )
1080 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001081 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001082 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001083 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001084 X->s = s;
1085 }
1086 else
1087 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001088 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001089 X->s = -s;
1090 }
1091 }
1092 else
1093 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001094 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001095 X->s = s;
1096 }
1097
1098cleanup:
1099
1100 return( ret );
1101}
1102
1103/*
1104 * Signed addition: X = A + b
1105 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001106int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001107{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001108 mbedtls_mpi _B;
1109 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001110
1111 p[0] = ( b < 0 ) ? -b : b;
1112 _B.s = ( b < 0 ) ? -1 : 1;
1113 _B.n = 1;
1114 _B.p = p;
1115
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001116 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001117}
1118
1119/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001120 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001121 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001122int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001123{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001124 mbedtls_mpi _B;
1125 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001126
1127 p[0] = ( b < 0 ) ? -b : b;
1128 _B.s = ( b < 0 ) ? -1 : 1;
1129 _B.n = 1;
1130 _B.p = p;
1131
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001132 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001133}
1134
1135/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001136 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001137 */
1138static
1139#if defined(__APPLE__) && defined(__arm__)
1140/*
1141 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1142 * appears to need this to prevent bad ARM code generation at -O3.
1143 */
1144__attribute__ ((noinline))
1145#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001146void 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 +00001147{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001148 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001149
1150#if defined(MULADDC_HUIT)
1151 for( ; i >= 8; i -= 8 )
1152 {
1153 MULADDC_INIT
1154 MULADDC_HUIT
1155 MULADDC_STOP
1156 }
1157
1158 for( ; i > 0; i-- )
1159 {
1160 MULADDC_INIT
1161 MULADDC_CORE
1162 MULADDC_STOP
1163 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001164#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001165 for( ; i >= 16; i -= 16 )
1166 {
1167 MULADDC_INIT
1168 MULADDC_CORE MULADDC_CORE
1169 MULADDC_CORE MULADDC_CORE
1170 MULADDC_CORE MULADDC_CORE
1171 MULADDC_CORE MULADDC_CORE
1172
1173 MULADDC_CORE MULADDC_CORE
1174 MULADDC_CORE MULADDC_CORE
1175 MULADDC_CORE MULADDC_CORE
1176 MULADDC_CORE MULADDC_CORE
1177 MULADDC_STOP
1178 }
1179
1180 for( ; i >= 8; i -= 8 )
1181 {
1182 MULADDC_INIT
1183 MULADDC_CORE MULADDC_CORE
1184 MULADDC_CORE MULADDC_CORE
1185
1186 MULADDC_CORE MULADDC_CORE
1187 MULADDC_CORE MULADDC_CORE
1188 MULADDC_STOP
1189 }
1190
1191 for( ; i > 0; i-- )
1192 {
1193 MULADDC_INIT
1194 MULADDC_CORE
1195 MULADDC_STOP
1196 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001197#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001198
1199 t++;
1200
1201 do {
1202 *d += c; c = ( *d < c ); d++;
1203 }
1204 while( c != 0 );
1205}
1206
1207/*
1208 * Baseline multiplication: X = A * B (HAC 14.12)
1209 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001210int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001211{
Paul Bakker23986e52011-04-24 08:57:21 +00001212 int ret;
1213 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001214 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001215
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001216 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001218 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1219 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001220
Paul Bakker23986e52011-04-24 08:57:21 +00001221 for( i = A->n; i > 0; i-- )
1222 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001223 break;
1224
Paul Bakker23986e52011-04-24 08:57:21 +00001225 for( j = B->n; j > 0; j-- )
1226 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001227 break;
1228
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001229 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1230 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001231
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001232 for( ; j > 0; j-- )
1233 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001234
1235 X->s = A->s * B->s;
1236
1237cleanup:
1238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001239 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001240
1241 return( ret );
1242}
1243
1244/*
1245 * Baseline multiplication: X = A * b
1246 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001247int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001248{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001249 mbedtls_mpi _B;
1250 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001251
1252 _B.s = 1;
1253 _B.n = 1;
1254 _B.p = p;
1255 p[0] = b;
1256
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001257 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001258}
1259
1260/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001261 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1262 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001263 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001264static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1265 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001266{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001267#if defined(MBEDTLS_HAVE_UDBL)
1268 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001269#else
Simon Butcher9803d072016-01-03 00:24:34 +00001270 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1271 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001272 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1273 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001274 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001275#endif
1276
Simon Butcher15b15d12015-11-26 19:35:03 +00001277 /*
1278 * Check for overflow
1279 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001280 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001281 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001282 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001283
Simon Butcherf5ba0452015-12-27 23:01:55 +00001284 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001285 }
1286
1287#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001288 dividend = (mbedtls_t_udbl) u1 << biL;
1289 dividend |= (mbedtls_t_udbl) u0;
1290 quotient = dividend / d;
1291 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1292 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1293
1294 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001295 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001296
1297 return (mbedtls_mpi_uint) quotient;
1298#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001299
1300 /*
1301 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1302 * Vol. 2 - Seminumerical Algorithms, Knuth
1303 */
1304
1305 /*
1306 * Normalize the divisor, d, and dividend, u0, u1
1307 */
1308 s = mbedtls_clz( d );
1309 d = d << s;
1310
1311 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001312 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001313 u0 = u0 << s;
1314
1315 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001316 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001317
1318 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001319 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001320
1321 /*
1322 * Find the first quotient and remainder
1323 */
1324 q1 = u1 / d1;
1325 r0 = u1 - d1 * q1;
1326
1327 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1328 {
1329 q1 -= 1;
1330 r0 += d1;
1331
1332 if ( r0 >= radix ) break;
1333 }
1334
Simon Butcherf5ba0452015-12-27 23:01:55 +00001335 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001336 q0 = rAX / d1;
1337 r0 = rAX - q0 * d1;
1338
1339 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1340 {
1341 q0 -= 1;
1342 r0 += d1;
1343
1344 if ( r0 >= radix ) break;
1345 }
1346
1347 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001348 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001349
1350 quotient = q1 * radix + q0;
1351
1352 return quotient;
1353#endif
1354}
1355
1356/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001357 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001358 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001359int 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 +00001360{
Paul Bakker23986e52011-04-24 08:57:21 +00001361 int ret;
1362 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001363 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001364
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1366 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001367
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001368 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1369 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001370
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001371 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001372 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001373 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1374 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001375 return( 0 );
1376 }
1377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001378 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1379 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001380 X.s = Y.s = 1;
1381
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001382 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1383 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1384 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1385 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001386
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001387 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001388 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001389 {
1390 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1392 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001393 }
1394 else k = 0;
1395
1396 n = X.n - 1;
1397 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001398 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001401 {
1402 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001404 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001405 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001406
1407 for( i = n; i > t ; i-- )
1408 {
1409 if( X.p[i] >= Y.p[t] )
1410 Z.p[i - t - 1] = ~0;
1411 else
1412 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001413 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1414 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001415 }
1416
1417 Z.p[i - t - 1]++;
1418 do
1419 {
1420 Z.p[i - t - 1]--;
1421
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001422 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001423 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001424 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001425 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001426
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001427 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001428 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1429 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001430 T2.p[2] = X.p[i];
1431 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001432 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001434 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1435 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1436 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001437
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001438 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001439 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001440 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1441 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1442 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001443 Z.p[i - t - 1]--;
1444 }
1445 }
1446
1447 if( Q != NULL )
1448 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001449 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001450 Q->s = A->s * B->s;
1451 }
1452
1453 if( R != NULL )
1454 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001455 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001456 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001457 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001459 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001460 R->s = 1;
1461 }
1462
1463cleanup:
1464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001465 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1466 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001467
1468 return( ret );
1469}
1470
1471/*
1472 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001473 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001474int 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 +00001475{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001476 mbedtls_mpi _B;
1477 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001478
1479 p[0] = ( b < 0 ) ? -b : b;
1480 _B.s = ( b < 0 ) ? -1 : 1;
1481 _B.n = 1;
1482 _B.p = p;
1483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001484 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001485}
1486
1487/*
1488 * Modulo: R = A mod B
1489 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001490int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001491{
1492 int ret;
1493
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001494 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1495 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001497 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001499 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1500 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001501
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001502 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1503 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001504
1505cleanup:
1506
1507 return( ret );
1508}
1509
1510/*
1511 * Modulo: r = A mod b
1512 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001513int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001514{
Paul Bakker23986e52011-04-24 08:57:21 +00001515 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001516 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001517
1518 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001519 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001520
1521 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001522 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001523
1524 /*
1525 * handle trivial cases
1526 */
1527 if( b == 1 )
1528 {
1529 *r = 0;
1530 return( 0 );
1531 }
1532
1533 if( b == 2 )
1534 {
1535 *r = A->p[0] & 1;
1536 return( 0 );
1537 }
1538
1539 /*
1540 * general case
1541 */
Paul Bakker23986e52011-04-24 08:57:21 +00001542 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001543 {
Paul Bakker23986e52011-04-24 08:57:21 +00001544 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001545 y = ( y << biH ) | ( x >> biH );
1546 z = y / b;
1547 y -= z * b;
1548
1549 x <<= biH;
1550 y = ( y << biH ) | ( x >> biH );
1551 z = y / b;
1552 y -= z * b;
1553 }
1554
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001555 /*
1556 * If A is negative, then the current y represents a negative value.
1557 * Flipping it to the positive side.
1558 */
1559 if( A->s < 0 && y != 0 )
1560 y = b - y;
1561
Paul Bakker5121ce52009-01-03 21:22:43 +00001562 *r = y;
1563
1564 return( 0 );
1565}
1566
1567/*
1568 * Fast Montgomery initialization (thanks to Tom St Denis)
1569 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001570static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001571{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001572 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001573 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001574
1575 x = m0;
1576 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001577
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001578 for( i = biL; i >= 8; i /= 2 )
1579 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001580
1581 *mm = ~x + 1;
1582}
1583
1584/*
1585 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1586 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001587static 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 +02001588 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001589{
Paul Bakker23986e52011-04-24 08:57:21 +00001590 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001591 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001592
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001593 if( T->n < N->n + 1 || T->p == NULL )
1594 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1595
Paul Bakker5121ce52009-01-03 21:22:43 +00001596 memset( T->p, 0, T->n * ciL );
1597
1598 d = T->p;
1599 n = N->n;
1600 m = ( B->n < n ) ? B->n : n;
1601
1602 for( i = 0; i < n; i++ )
1603 {
1604 /*
1605 * T = (T + u0*B + u1*N) / 2^biL
1606 */
1607 u0 = A->p[i];
1608 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1609
1610 mpi_mul_hlp( m, B->p, d, u0 );
1611 mpi_mul_hlp( n, N->p, d, u1 );
1612
1613 *d++ = u0; d[n + 1] = 0;
1614 }
1615
Paul Bakker66d5d072014-06-17 16:39:18 +02001616 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001617
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001618 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001619 mpi_sub_hlp( n, N->p, A->p );
1620 else
1621 /* prevent timing attacks */
1622 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001623
1624 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001625}
1626
1627/*
1628 * Montgomery reduction: A = A * R^-1 mod N
1629 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001630static 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 +00001631{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001632 mbedtls_mpi_uint z = 1;
1633 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001634
Paul Bakker8ddb6452013-02-27 14:56:33 +01001635 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001636 U.p = &z;
1637
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001638 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001639}
1640
1641/*
1642 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1643 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001644int 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 +00001645{
Paul Bakker23986e52011-04-24 08:57:21 +00001646 int ret;
1647 size_t wbits, wsize, one = 1;
1648 size_t i, j, nblimbs;
1649 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001650 mbedtls_mpi_uint ei, mm, state;
1651 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001652 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001653
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001654 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001655 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001656
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001657 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1658 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001659
1660 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001661 * Init temps and window size
1662 */
1663 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001664 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1665 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001666 memset( W, 0, sizeof( W ) );
1667
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001668 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001669
1670 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1671 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1672
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001673 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1674 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001675
Paul Bakker5121ce52009-01-03 21:22:43 +00001676 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001677 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1678 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1679 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001680
1681 /*
Paul Bakker50546922012-05-19 08:40:49 +00001682 * Compensate for negative A (and correct at the end)
1683 */
1684 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001685 if( neg )
1686 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001687 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001688 Apos.s = 1;
1689 A = &Apos;
1690 }
1691
1692 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001693 * If 1st call, pre-compute R^2 mod N
1694 */
1695 if( _RR == NULL || _RR->p == NULL )
1696 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001697 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1698 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1699 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001700
1701 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001702 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001703 }
1704 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001705 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001706
1707 /*
1708 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1709 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001710 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1711 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001712 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001713 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001714
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001715 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001716
1717 /*
1718 * X = R^2 * R^-1 mod N = R mod N
1719 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001720 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001721 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001722
1723 if( wsize > 1 )
1724 {
1725 /*
1726 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1727 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001728 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001729
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001730 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1731 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001732
1733 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001734 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001735
Paul Bakker5121ce52009-01-03 21:22:43 +00001736 /*
1737 * W[i] = W[i - 1] * W[1]
1738 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001739 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001740 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001741 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1742 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001743
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001744 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001745 }
1746 }
1747
1748 nblimbs = E->n;
1749 bufsize = 0;
1750 nbits = 0;
1751 wbits = 0;
1752 state = 0;
1753
1754 while( 1 )
1755 {
1756 if( bufsize == 0 )
1757 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001758 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001759 break;
1760
Paul Bakker0d7702c2013-10-29 16:18:35 +01001761 nblimbs--;
1762
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001763 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001764 }
1765
1766 bufsize--;
1767
1768 ei = (E->p[nblimbs] >> bufsize) & 1;
1769
1770 /*
1771 * skip leading 0s
1772 */
1773 if( ei == 0 && state == 0 )
1774 continue;
1775
1776 if( ei == 0 && state == 1 )
1777 {
1778 /*
1779 * out of window, square X
1780 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001781 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001782 continue;
1783 }
1784
1785 /*
1786 * add ei to current window
1787 */
1788 state = 2;
1789
1790 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001791 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001792
1793 if( nbits == wsize )
1794 {
1795 /*
1796 * X = X^wsize R^-1 mod N
1797 */
1798 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001799 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001800
1801 /*
1802 * X = X * W[wbits] R^-1 mod N
1803 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001804 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001805
1806 state--;
1807 nbits = 0;
1808 wbits = 0;
1809 }
1810 }
1811
1812 /*
1813 * process the remaining bits
1814 */
1815 for( i = 0; i < nbits; i++ )
1816 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001817 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001818
1819 wbits <<= 1;
1820
Paul Bakker66d5d072014-06-17 16:39:18 +02001821 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001822 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001823 }
1824
1825 /*
1826 * X = A^E * R * R^-1 mod N = A^E mod N
1827 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001828 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001829
Hanno Beckera4af1c42017-04-18 09:07:45 +01001830 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001831 {
1832 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001833 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001834 }
1835
Paul Bakker5121ce52009-01-03 21:22:43 +00001836cleanup:
1837
Paul Bakker66d5d072014-06-17 16:39:18 +02001838 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001839 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001840
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001841 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001842
Paul Bakker75a28602014-03-31 12:08:17 +02001843 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001845
1846 return( ret );
1847}
1848
Paul Bakker5121ce52009-01-03 21:22:43 +00001849/*
1850 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1851 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001852int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001853{
Paul Bakker23986e52011-04-24 08:57:21 +00001854 int ret;
1855 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001856 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001857
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001858 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001859
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001860 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1861 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001862
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001863 lz = mbedtls_mpi_lsb( &TA );
1864 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001865
Paul Bakker66d5d072014-06-17 16:39:18 +02001866 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001867 lz = lzt;
1868
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001869 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1870 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001871
Paul Bakker5121ce52009-01-03 21:22:43 +00001872 TA.s = TB.s = 1;
1873
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001874 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001875 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001876 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1877 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001878
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001880 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001881 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1882 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001883 }
1884 else
1885 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001886 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1887 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001888 }
1889 }
1890
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001891 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1892 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001893
1894cleanup:
1895
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001896 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001897
1898 return( ret );
1899}
1900
Paul Bakker33dc46b2014-04-30 16:11:39 +02001901/*
1902 * Fill X with size bytes of random.
1903 *
1904 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001905 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001906 * deterministic, eg for tests).
1907 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001908int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001909 int (*f_rng)(void *, unsigned char *, size_t),
1910 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001911{
Paul Bakker23986e52011-04-24 08:57:21 +00001912 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001913 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001914
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001915 if( size > MBEDTLS_MPI_MAX_SIZE )
1916 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001917
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001918 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1919 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001920
1921cleanup:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -05001922 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001923 return( ret );
1924}
1925
Paul Bakker5121ce52009-01-03 21:22:43 +00001926/*
1927 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1928 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001930{
1931 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001932 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001933
Hanno Becker4bcb4912017-04-18 15:49:39 +01001934 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001935 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001936
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001937 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1938 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1939 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001940
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001941 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001942
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001943 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001944 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001945 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001946 goto cleanup;
1947 }
1948
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001949 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1950 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1951 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1952 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001953
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001954 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1955 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1956 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1957 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001958
1959 do
1960 {
1961 while( ( TU.p[0] & 1 ) == 0 )
1962 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001964
1965 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1966 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001967 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1968 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001969 }
1970
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001971 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1972 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001973 }
1974
1975 while( ( TV.p[0] & 1 ) == 0 )
1976 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001977 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001978
1979 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1980 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001981 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1982 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001983 }
1984
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001985 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1986 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001987 }
1988
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001989 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001990 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001991 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1992 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1993 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001994 }
1995 else
1996 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001997 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1998 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1999 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002000 }
2001 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002002 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002003
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002004 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2005 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002006
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002007 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2008 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002009
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002010 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002011
2012cleanup:
2013
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002014 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2015 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2016 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002017
2018 return( ret );
2019}
2020
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002021#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002022
Paul Bakker5121ce52009-01-03 21:22:43 +00002023static const int small_prime[] =
2024{
2025 3, 5, 7, 11, 13, 17, 19, 23,
2026 29, 31, 37, 41, 43, 47, 53, 59,
2027 61, 67, 71, 73, 79, 83, 89, 97,
2028 101, 103, 107, 109, 113, 127, 131, 137,
2029 139, 149, 151, 157, 163, 167, 173, 179,
2030 181, 191, 193, 197, 199, 211, 223, 227,
2031 229, 233, 239, 241, 251, 257, 263, 269,
2032 271, 277, 281, 283, 293, 307, 311, 313,
2033 317, 331, 337, 347, 349, 353, 359, 367,
2034 373, 379, 383, 389, 397, 401, 409, 419,
2035 421, 431, 433, 439, 443, 449, 457, 461,
2036 463, 467, 479, 487, 491, 499, 503, 509,
2037 521, 523, 541, 547, 557, 563, 569, 571,
2038 577, 587, 593, 599, 601, 607, 613, 617,
2039 619, 631, 641, 643, 647, 653, 659, 661,
2040 673, 677, 683, 691, 701, 709, 719, 727,
2041 733, 739, 743, 751, 757, 761, 769, 773,
2042 787, 797, 809, 811, 821, 823, 827, 829,
2043 839, 853, 857, 859, 863, 877, 881, 883,
2044 887, 907, 911, 919, 929, 937, 941, 947,
2045 953, 967, 971, 977, 983, 991, 997, -103
2046};
2047
2048/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002049 * Small divisors test (X must be positive)
2050 *
2051 * Return values:
2052 * 0: no small factor (possible prime, more tests needed)
2053 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002054 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002055 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002056 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002057static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002058{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002059 int ret = 0;
2060 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002061 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002062
Paul Bakker5121ce52009-01-03 21:22:43 +00002063 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002064 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002065
2066 for( i = 0; small_prime[i] > 0; i++ )
2067 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002068 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002069 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002070
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002071 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002072
2073 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002074 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002075 }
2076
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002077cleanup:
2078 return( ret );
2079}
2080
2081/*
2082 * Miller-Rabin pseudo-primality test (HAC 4.24)
2083 */
Janos Follathda31fa12018-09-03 14:45:23 +01002084static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002085 int (*f_rng)(void *, unsigned char *, size_t),
2086 void *p_rng )
2087{
Pascal Junodb99183d2015-03-11 16:49:45 +01002088 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002089 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002090 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002091
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002092 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2093 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002094
Paul Bakker5121ce52009-01-03 21:22:43 +00002095 /*
2096 * W = |X| - 1
2097 * R = W >> lsb( W )
2098 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002099 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2100 s = mbedtls_mpi_lsb( &W );
2101 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2102 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002103
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002104 i = mbedtls_mpi_bitlen( X );
Janos Follathf301d232018-08-14 13:34:01 +01002105
Janos Follathda31fa12018-09-03 14:45:23 +01002106 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002107 {
2108 /*
2109 * pick a random A, 1 < A < |X| - 1
2110 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002111 count = 0;
2112 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002113 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002114
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002115 j = mbedtls_mpi_bitlen( &A );
2116 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002117 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002118 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002119 }
2120
2121 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002122 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002123 }
2124
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002125 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2126 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002127
2128 /*
2129 * A = A^R mod |X|
2130 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002131 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002132
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002133 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2134 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002135 continue;
2136
2137 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002138 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002139 {
2140 /*
2141 * A = A * A mod |X|
2142 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002143 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2144 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002145
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002146 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002147 break;
2148
2149 j++;
2150 }
2151
2152 /*
2153 * not prime if A != |X| - 1 or A == 1
2154 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002155 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2156 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002157 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002158 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002159 break;
2160 }
2161 }
2162
2163cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002164 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2165 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002166
2167 return( ret );
2168}
2169
2170/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002171 * Pseudo-primality test: small factors, then Miller-Rabin
2172 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002173int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2174 int (*f_rng)(void *, unsigned char *, size_t),
2175 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002176{
2177 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002178 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002179
2180 XX.s = 1;
2181 XX.n = X->n;
2182 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2185 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2186 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002187
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002189 return( 0 );
2190
2191 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2192 {
2193 if( ret == 1 )
2194 return( 0 );
2195
2196 return( ret );
2197 }
2198
Janos Follathda31fa12018-09-03 14:45:23 +01002199 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002200}
2201
Janos Follatha0b67c22018-09-18 14:48:23 +01002202#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002203/*
2204 * Pseudo-primality test, error probability 2^-80
2205 */
2206int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2207 int (*f_rng)(void *, unsigned char *, size_t),
2208 void *p_rng )
2209{
Janos Follatha0b67c22018-09-18 14:48:23 +01002210 /*
2211 * In the past our key generation aimed for an error rate of at most
2212 * 2^-80. Since this function is deprecated, aim for the same certainty
2213 * here as well.
2214 */
2215 return mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002216}
Janos Follatha0b67c22018-09-18 14:48:23 +01002217#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002218
2219/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002220 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002221 *
Janos Follathf301d232018-08-14 13:34:01 +01002222 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2223 * be either 1024 bits or 1536 bits long, and flags must contain
2224 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002225 */
Janos Follath7c025a92018-08-14 11:08:41 +01002226int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002227 int (*f_rng)(void *, unsigned char *, size_t),
2228 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002229{
Jethro Beekman66689272018-02-14 19:24:10 -08002230#ifdef MBEDTLS_HAVE_INT64
2231// ceil(2^63.5)
2232#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2233#else
2234// ceil(2^31.5)
2235#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2236#endif
2237 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002238 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002239 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002240 mbedtls_mpi_uint r;
2241 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002242
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002243 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2244 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002245
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002246 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002247
2248 n = BITS_TO_LIMBS( nbits );
2249
Janos Follathda31fa12018-09-03 14:45:23 +01002250 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2251 {
2252 /*
2253 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2254 */
2255 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2256 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2257 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2258 }
2259 else
2260 {
2261 /*
2262 * 2^-100 error probability, number of rounds computed based on HAC,
2263 * fact 4.48
2264 */
2265 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2266 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2267 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2268 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2269 }
2270
Jethro Beekman66689272018-02-14 19:24:10 -08002271 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002272 {
Jethro Beekman66689272018-02-14 19:24:10 -08002273 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2274 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2275 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2276
2277 k = n * biL;
2278 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2279 X->p[0] |= 1;
2280
Janos Follath7c025a92018-08-14 11:08:41 +01002281 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002282 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002283 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002284
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002285 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002286 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002287 }
Jethro Beekman66689272018-02-14 19:24:10 -08002288 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002289 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002290 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002291 * An necessary condition for Y and X = 2Y + 1 to be prime
2292 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2293 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002294 */
Jethro Beekman66689272018-02-14 19:24:10 -08002295
2296 X->p[0] |= 2;
2297
2298 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2299 if( r == 0 )
2300 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2301 else if( r == 1 )
2302 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2303
2304 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2305 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2306 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2307
2308 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002309 {
Jethro Beekman66689272018-02-14 19:24:10 -08002310 /*
2311 * First, check small factors for X and Y
2312 * before doing Miller-Rabin on any of them
2313 */
2314 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2315 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002316 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002317 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002318 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002319 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002320 goto cleanup;
2321
2322 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2323 goto cleanup;
2324
2325 /*
2326 * Next candidates. We want to preserve Y = (X-1) / 2 and
2327 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2328 * so up Y by 6 and X by 12.
2329 */
2330 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2331 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002332 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002333 }
2334 }
2335
2336cleanup:
2337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002339
2340 return( ret );
2341}
2342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002343#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002345#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
Paul Bakker23986e52011-04-24 08:57:21 +00002347#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002348
2349static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2350{
2351 { 693, 609, 21 },
2352 { 1764, 868, 28 },
2353 { 768454923, 542167814, 1 }
2354};
2355
Paul Bakker5121ce52009-01-03 21:22:43 +00002356/*
2357 * Checkup routine
2358 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002360{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002361 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002362 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002363
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002364 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2365 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002366
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002368 "EFE021C2645FD1DC586E69184AF4A31E" \
2369 "D5F53E93B5F123FA41680867BA110131" \
2370 "944FE7952E2517337780CB0DB80E61AA" \
2371 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2372
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002373 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002374 "B2E7EFD37075B9F03FF989C7C5051C20" \
2375 "34D2A323810251127E7BF8625A4F49A5" \
2376 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2377 "5B5C25763222FEFCCFC38B832366C29E" ) );
2378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002379 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002380 "0066A198186C18C10B2F5ED9B522752A" \
2381 "9830B69916E535C8F047518A889A43A5" \
2382 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2383
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002384 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002385
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002386 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002387 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2388 "9E857EA95A03512E2BAE7391688D264A" \
2389 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2390 "8001B72E848A38CAE1C65F78E56ABDEF" \
2391 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2392 "ECF677152EF804370C1A305CAF3B5BF1" \
2393 "30879B56C61DE584A0F53A2447A51E" ) );
2394
2395 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002397
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002398 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002399 {
2400 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002401 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002402
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002403 ret = 1;
2404 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002405 }
2406
2407 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002408 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002409
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002410 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002411
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002412 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002413 "256567336059E52CAE22925474705F39A94" ) );
2414
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002415 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002416 "6613F26162223DF488E9CD48CC132C7A" \
2417 "0AC93C701B001B092E4E5B9F73BCD27B" \
2418 "9EE50D0657C77F374E903CDFA4C642" ) );
2419
2420 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002421 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002422
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002423 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2424 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002425 {
2426 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002427 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002428
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002429 ret = 1;
2430 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002431 }
2432
2433 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002435
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002436 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002437
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002438 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002439 "36E139AEA55215609D2816998ED020BB" \
2440 "BD96C37890F65171D948E9BC7CBAA4D9" \
2441 "325D24D6A3C12710F10A09FA08AB87" ) );
2442
2443 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002444 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002446 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002447 {
2448 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002449 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002450
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002451 ret = 1;
2452 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002453 }
2454
2455 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002456 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002457
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002458 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002460 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002461 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2462 "C3DBA76456363A10869622EAC2DD84EC" \
2463 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2464
2465 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002466 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002468 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002469 {
2470 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002471 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002472
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002473 ret = 1;
2474 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002475 }
2476
2477 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002478 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002479
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002480 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002481 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002482
Paul Bakker66d5d072014-06-17 16:39:18 +02002483 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002484 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002485 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2486 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002487
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002488 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002489
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002490 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002491 {
2492 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002493 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002494
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002495 ret = 1;
2496 goto cleanup;
2497 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002498 }
2499
2500 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002501 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002502
Paul Bakker5121ce52009-01-03 21:22:43 +00002503cleanup:
2504
2505 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002506 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002508 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2509 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002510
2511 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002512 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002513
2514 return( ret );
2515}
2516
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002517#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002518
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002519#endif /* MBEDTLS_BIGNUM_C */