blob: f6e50b986a070dbbcd96c9d34f9031f21ea441a7 [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"
Paul Bakker5121ce52009-01-03 21:22:43 +000048
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <string.h>
50
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000052#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020053#else
Rich Evans00ab4702015-02-06 13:43:58 +000054#include <stdio.h>
55#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020057#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020059#endif
60
Paul Bakker34617722014-06-13 17:20:13 +020061/* Implementation that should never be optimized out by the compiler */
Alexey Skalozube17a8da2016-01-13 17:19:33 +020062static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) {
Alexey Skalozub3d53f412016-01-13 16:53:40 +020063 volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0;
Paul Bakker34617722014-06-13 17:20:13 +020064}
65
Hanno Becker88807112017-10-18 12:41:30 +010066/* Implementation that should never be optimized out by the compiler */
67static void mbedtls_zeroize( void *v, size_t n ) {
68 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
69}
70
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000072#define biL (ciL << 3) /* bits in limb */
73#define biH (ciL << 2) /* half limb size */
74
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010075#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
76
Paul Bakker5121ce52009-01-03 21:22:43 +000077/*
78 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020079 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000080 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020081#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
82#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000083
84/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000085 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000086 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020087void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000088{
Paul Bakker6c591fa2011-05-05 11:49:20 +000089 if( X == NULL )
90 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000091
Paul Bakker6c591fa2011-05-05 11:49:20 +000092 X->s = 1;
93 X->n = 0;
94 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000095}
96
97/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000098 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000099 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000101{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000102 if( X == NULL )
103 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000104
Paul Bakker6c591fa2011-05-05 11:49:20 +0000105 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000106 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200107 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200108 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000109 }
110
Paul Bakker6c591fa2011-05-05 11:49:20 +0000111 X->s = 1;
112 X->n = 0;
113 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000114}
115
116/*
117 * Enlarge to the specified number of limbs
118 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000120{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200123 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200124 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000125
Paul Bakker5121ce52009-01-03 21:22:43 +0000126 if( X->n < nblimbs )
127 {
Simon Butcher29176892016-05-20 00:19:09 +0100128 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200129 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000130
Paul Bakker5121ce52009-01-03 21:22:43 +0000131 if( X->p != NULL )
132 {
133 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200134 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000136 }
137
138 X->n = nblimbs;
139 X->p = p;
140 }
141
142 return( 0 );
143}
144
145/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100146 * Resize down as much as possible,
147 * while keeping at least the specified number of limbs
148 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100150{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152 size_t i;
153
154 /* Actually resize up in this case */
155 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100157
158 for( i = X->n - 1; i > 0; i-- )
159 if( X->p[i] != 0 )
160 break;
161 i++;
162
163 if( i < nblimbs )
164 i = nblimbs;
165
Simon Butcher29176892016-05-20 00:19:09 +0100166 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200167 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100168
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100169 if( X->p != NULL )
170 {
171 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200172 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100174 }
175
176 X->n = i;
177 X->p = p;
178
179 return( 0 );
180}
181
182/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000183 * Copy the contents of Y into X
184 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000186{
Paul Bakker23986e52011-04-24 08:57:21 +0000187 int ret;
188 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000189
190 if( X == Y )
191 return( 0 );
192
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200193 if( Y->p == NULL )
194 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200195 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200196 return( 0 );
197 }
198
Paul Bakker5121ce52009-01-03 21:22:43 +0000199 for( i = Y->n - 1; i > 0; i-- )
200 if( Y->p[i] != 0 )
201 break;
202 i++;
203
204 X->s = Y->s;
205
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000207
208 memset( X->p, 0, X->n * ciL );
209 memcpy( X->p, Y->p, i * ciL );
210
211cleanup:
212
213 return( ret );
214}
215
216/*
217 * Swap the contents of X and Y
218 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000220{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200223 memcpy( &T, X, sizeof( mbedtls_mpi ) );
224 memcpy( X, Y, sizeof( mbedtls_mpi ) );
225 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000226}
227
228/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100229 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100230 * about whether the assignment was made or not.
231 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100234{
235 int ret = 0;
236 size_t i;
237
Pascal Junodb99183d2015-03-11 16:49:45 +0100238 /* make sure assign is 0 or 1 in a time-constant manner */
239 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100242
Paul Bakker66d5d072014-06-17 16:39:18 +0200243 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100244
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100245 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200246 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100247
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100248 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200249 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250
251cleanup:
252 return( ret );
253}
254
255/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100256 * Conditionally swap X and Y, without leaking information
257 * about whether the swap was made or not.
258 * Here it is not ok to simply swap the pointers, which whould lead to
259 * different memory access patterns when X and Y are used afterwards.
260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100262{
263 int ret, s;
264 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100266
267 if( X == Y )
268 return( 0 );
269
Pascal Junodb99183d2015-03-11 16:49:45 +0100270 /* make sure swap is 0 or 1 in a time-constant manner */
271 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100272
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200273 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
274 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100275
276 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200277 X->s = X->s * ( 1 - swap ) + Y->s * swap;
278 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100279
280
281 for( i = 0; i < X->n; i++ )
282 {
283 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200284 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
285 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286 }
287
288cleanup:
289 return( ret );
290}
291
292/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000293 * Set value from integer
294 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200295int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000296{
297 int ret;
298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000300 memset( X->p, 0, X->n * ciL );
301
302 X->p[0] = ( z < 0 ) ? -z : z;
303 X->s = ( z < 0 ) ? -1 : 1;
304
305cleanup:
306
307 return( ret );
308}
309
310/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000311 * Get a specific bit
312 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200313int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000314{
315 if( X->n * biL <= pos )
316 return( 0 );
317
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200318 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000319}
320
Gilles Peskine220cc172018-11-20 16:47:47 +0100321/* Get a specific byte, without range checks. */
322#define GET_BYTE( X, i ) \
323 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
324
Paul Bakker2f5947e2011-05-18 15:47:11 +0000325/*
326 * Set a bit to a specific value of 0 or 1
327 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200328int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000329{
330 int ret = 0;
331 size_t off = pos / biL;
332 size_t idx = pos % biL;
333
334 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200335 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200336
Paul Bakker2f5947e2011-05-18 15:47:11 +0000337 if( X->n * biL <= pos )
338 {
339 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200340 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200342 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000343 }
344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200345 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
346 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000347
348cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200349
Paul Bakker2f5947e2011-05-18 15:47:11 +0000350 return( ret );
351}
352
353/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200354 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000355 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000357{
Paul Bakker23986e52011-04-24 08:57:21 +0000358 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000359
360 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000361 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000362 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
363 return( count );
364
365 return( 0 );
366}
367
368/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000369 * Count leading zero bits in a given integer
370 */
371static size_t mbedtls_clz( const mbedtls_mpi_uint x )
372{
373 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100374 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000375
376 for( j = 0; j < biL; j++ )
377 {
378 if( x & mask ) break;
379
380 mask >>= 1;
381 }
382
383 return j;
384}
385
386/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200387 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000388 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200389size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000390{
Paul Bakker23986e52011-04-24 08:57:21 +0000391 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000392
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200393 if( X->n == 0 )
394 return( 0 );
395
Paul Bakker5121ce52009-01-03 21:22:43 +0000396 for( i = X->n - 1; i > 0; i-- )
397 if( X->p[i] != 0 )
398 break;
399
Simon Butcher15b15d12015-11-26 19:35:03 +0000400 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000401
Paul Bakker23986e52011-04-24 08:57:21 +0000402 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000403}
404
405/*
406 * Return the total size in bytes
407 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000409{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200410 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000411}
412
413/*
414 * Convert an ASCII character to digit value
415 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000417{
418 *d = 255;
419
420 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
421 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
422 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424 if( *d >= (mbedtls_mpi_uint) radix )
425 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
427 return( 0 );
428}
429
430/*
431 * Import from an ASCII string
432 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000434{
Paul Bakker23986e52011-04-24 08:57:21 +0000435 int ret;
436 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437 mbedtls_mpi_uint d;
438 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000439
440 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200443 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000444
Paul Bakkerff60ee62010-03-16 21:09:09 +0000445 slen = strlen( s );
446
Paul Bakker5121ce52009-01-03 21:22:43 +0000447 if( radix == 16 )
448 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100449 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200450 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
451
Paul Bakkerff60ee62010-03-16 21:09:09 +0000452 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000453
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
455 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000456
Paul Bakker23986e52011-04-24 08:57:21 +0000457 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 {
Paul Bakker23986e52011-04-24 08:57:21 +0000459 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000460 {
461 X->s = -1;
462 break;
463 }
464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200466 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000467 }
468 }
469 else
470 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000472
Paul Bakkerff60ee62010-03-16 21:09:09 +0000473 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 {
475 if( i == 0 && s[i] == '-' )
476 {
477 X->s = -1;
478 continue;
479 }
480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
482 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000483
484 if( X->s == 1 )
485 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000487 }
488 else
489 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000491 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000492 }
493 }
494
495cleanup:
496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000498
499 return( ret );
500}
501
502/*
Ron Eldore6cbfc32018-11-20 14:07:01 +0200503 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000504 */
Ron Eldore6cbfc32018-11-20 14:07:01 +0200505static int mpi_write_hlp( mbedtls_mpi *X, int radix,
506 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000507{
508 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 mbedtls_mpi_uint r;
Ron Eldore6cbfc32018-11-20 14:07:01 +0200510 size_t length = 0;
511 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000512
Ron Eldore6cbfc32018-11-20 14:07:01 +0200513 do
514 {
515 if( length >= buflen )
516 {
517 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
518 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000519
Ron Eldore6cbfc32018-11-20 14:07:01 +0200520 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
521 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
522 /*
523 * Write the residue in the current position, as an ASCII character.
524 */
525 if( r < 0xA )
526 *(--p_end) = (char)( '0' + r );
527 else
528 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000529
Ron Eldore6cbfc32018-11-20 14:07:01 +0200530 length++;
531 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000532
Ron Eldore6cbfc32018-11-20 14:07:01 +0200533 memmove( *p, p_end, length );
534 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000535
536cleanup:
537
538 return( ret );
539}
540
541/*
542 * Export into an ASCII string
543 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100544int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
545 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000546{
Paul Bakker23986e52011-04-24 08:57:21 +0000547 int ret = 0;
548 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000549 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000551
552 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000554
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200555 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000556 if( radix >= 4 ) n >>= 1;
557 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000558 /*
559 * Round up the buffer length to an even value to ensure that there is
560 * enough room for hexadecimal values that can be represented in an odd
561 * number of digits.
562 */
563 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000564
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100565 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000566 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100567 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200568 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000569 }
570
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100571 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200572 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000573
574 if( X->s == -1 )
575 *p++ = '-';
576
577 if( radix == 16 )
578 {
Paul Bakker23986e52011-04-24 08:57:21 +0000579 int c;
580 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000581
Paul Bakker23986e52011-04-24 08:57:21 +0000582 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000583 {
Paul Bakker23986e52011-04-24 08:57:21 +0000584 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000585 {
Paul Bakker23986e52011-04-24 08:57:21 +0000586 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000587
Paul Bakker6c343d72014-07-10 14:36:19 +0200588 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000589 continue;
590
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000591 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000592 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000593 k = 1;
594 }
595 }
596 }
597 else
598 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000600
601 if( T.s == -1 )
602 T.s = 1;
603
Ron Eldore6cbfc32018-11-20 14:07:01 +0200604 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000605 }
606
607 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100608 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000609
610cleanup:
611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000613
614 return( ret );
615}
616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000618/*
619 * Read X from an opened file
620 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000622{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200623 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000624 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000625 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000626 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000627 * Buffer should have space for (short) label and decimal formatted MPI,
628 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000629 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000631
632 memset( s, 0, sizeof( s ) );
633 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200634 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000635
636 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000637 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000639
Hanno Beckerb2034b72017-04-26 11:46:46 +0100640 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
641 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000642
643 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100644 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000645 if( mpi_get_digit( &d, radix, *p ) != 0 )
646 break;
647
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000649}
650
651/*
652 * Write X into an opened file (or stdout if fout == NULL)
653 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200654int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000655{
Paul Bakker23986e52011-04-24 08:57:21 +0000656 int ret;
657 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000658 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000659 * Buffer should have space for (short) label and decimal formatted MPI,
660 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000661 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000663
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100664 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000665
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100666 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000667
668 if( p == NULL ) p = "";
669
670 plen = strlen( p );
671 slen = strlen( s );
672 s[slen++] = '\r';
673 s[slen++] = '\n';
674
675 if( fout != NULL )
676 {
677 if( fwrite( p, 1, plen, fout ) != plen ||
678 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200679 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000680 }
681 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000683
684cleanup:
685
686 return( ret );
687}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200688#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000689
690/*
691 * Import X from unsigned binary data, big endian
692 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200693int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000694{
Paul Bakker23986e52011-04-24 08:57:21 +0000695 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100696 size_t i, j;
697 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
Hanno Becker073c1992017-10-17 15:17:27 +0100699 /* Ensure that target MPI has exactly the necessary number of limbs */
700 if( X->n != limbs )
701 {
702 mbedtls_mpi_free( X );
703 mbedtls_mpi_init( X );
704 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
705 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000706
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000708
Hanno Becker073c1992017-10-17 15:17:27 +0100709 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
712cleanup:
713
714 return( ret );
715}
716
717/*
718 * Export X into unsigned binary data, big endian
719 */
Gilles Peskine220cc172018-11-20 16:47:47 +0100720int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
721 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000722{
Gilles Peskine220cc172018-11-20 16:47:47 +0100723 size_t stored_bytes = X->n * ciL;
724 size_t bytes_to_copy;
725 unsigned char *p;
726 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000727
Gilles Peskine220cc172018-11-20 16:47:47 +0100728 if( stored_bytes < buflen )
729 {
730 /* There is enough space in the output buffer. Write initial
731 * null bytes and record the position at which to start
732 * writing the significant bytes. In this case, the execution
733 * trace of this function does not depend on the value of the
734 * number. */
735 bytes_to_copy = stored_bytes;
736 p = buf + buflen - stored_bytes;
737 memset( buf, 0, buflen - stored_bytes );
738 }
739 else
740 {
741 /* The output buffer is smaller than the allocated size of X.
742 * However X may fit if its leading bytes are zero. */
743 bytes_to_copy = buflen;
744 p = buf;
745 for( i = bytes_to_copy; i < stored_bytes; i++ )
746 {
747 if( GET_BYTE( X, i ) != 0 )
748 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
749 }
750 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000751
Gilles Peskine220cc172018-11-20 16:47:47 +0100752 for( i = 0; i < bytes_to_copy; i++ )
753 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000754
755 return( 0 );
756}
757
758/*
759 * Left-shift: X <<= count
760 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200761int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000762{
Paul Bakker23986e52011-04-24 08:57:21 +0000763 int ret;
764 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200765 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000766
767 v0 = count / (biL );
768 t1 = count & (biL - 1);
769
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200770 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000771
Paul Bakkerf9688572011-05-05 10:00:45 +0000772 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200773 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000774
775 ret = 0;
776
777 /*
778 * shift by count / limb_size
779 */
780 if( v0 > 0 )
781 {
Paul Bakker23986e52011-04-24 08:57:21 +0000782 for( i = X->n; i > v0; i-- )
783 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000784
Paul Bakker23986e52011-04-24 08:57:21 +0000785 for( ; i > 0; i-- )
786 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000787 }
788
789 /*
790 * shift by count % limb_size
791 */
792 if( t1 > 0 )
793 {
794 for( i = v0; i < X->n; i++ )
795 {
796 r1 = X->p[i] >> (biL - t1);
797 X->p[i] <<= t1;
798 X->p[i] |= r0;
799 r0 = r1;
800 }
801 }
802
803cleanup:
804
805 return( ret );
806}
807
808/*
809 * Right-shift: X >>= count
810 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200811int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000812{
Paul Bakker23986e52011-04-24 08:57:21 +0000813 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200814 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000815
816 v0 = count / biL;
817 v1 = count & (biL - 1);
818
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100819 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200820 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100821
Paul Bakker5121ce52009-01-03 21:22:43 +0000822 /*
823 * shift by count / limb_size
824 */
825 if( v0 > 0 )
826 {
827 for( i = 0; i < X->n - v0; i++ )
828 X->p[i] = X->p[i + v0];
829
830 for( ; i < X->n; i++ )
831 X->p[i] = 0;
832 }
833
834 /*
835 * shift by count % limb_size
836 */
837 if( v1 > 0 )
838 {
Paul Bakker23986e52011-04-24 08:57:21 +0000839 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000840 {
Paul Bakker23986e52011-04-24 08:57:21 +0000841 r1 = X->p[i - 1] << (biL - v1);
842 X->p[i - 1] >>= v1;
843 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000844 r0 = r1;
845 }
846 }
847
848 return( 0 );
849}
850
851/*
852 * Compare unsigned values
853 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200854int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000855{
Paul Bakker23986e52011-04-24 08:57:21 +0000856 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000857
Paul Bakker23986e52011-04-24 08:57:21 +0000858 for( i = X->n; i > 0; i-- )
859 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000860 break;
861
Paul Bakker23986e52011-04-24 08:57:21 +0000862 for( j = Y->n; j > 0; j-- )
863 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000864 break;
865
Paul Bakker23986e52011-04-24 08:57:21 +0000866 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000867 return( 0 );
868
869 if( i > j ) return( 1 );
870 if( j > i ) return( -1 );
871
Paul Bakker23986e52011-04-24 08:57:21 +0000872 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000873 {
Paul Bakker23986e52011-04-24 08:57:21 +0000874 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
875 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000876 }
877
878 return( 0 );
879}
880
881/*
882 * Compare signed values
883 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200884int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000885{
Paul Bakker23986e52011-04-24 08:57:21 +0000886 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000887
Paul Bakker23986e52011-04-24 08:57:21 +0000888 for( i = X->n; i > 0; i-- )
889 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000890 break;
891
Paul Bakker23986e52011-04-24 08:57:21 +0000892 for( j = Y->n; j > 0; j-- )
893 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000894 break;
895
Paul Bakker23986e52011-04-24 08:57:21 +0000896 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000897 return( 0 );
898
899 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000900 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000901
902 if( X->s > 0 && Y->s < 0 ) return( 1 );
903 if( Y->s > 0 && X->s < 0 ) return( -1 );
904
Paul Bakker23986e52011-04-24 08:57:21 +0000905 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000906 {
Paul Bakker23986e52011-04-24 08:57:21 +0000907 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
908 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000909 }
910
911 return( 0 );
912}
913
914/*
915 * Compare signed values
916 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200917int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000918{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919 mbedtls_mpi Y;
920 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000921
922 *p = ( z < 0 ) ? -z : z;
923 Y.s = ( z < 0 ) ? -1 : 1;
924 Y.n = 1;
925 Y.p = p;
926
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200927 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000928}
929
930/*
931 * Unsigned addition: X = |A| + |B| (HAC 14.7)
932 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200933int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000934{
Paul Bakker23986e52011-04-24 08:57:21 +0000935 int ret;
936 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100937 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000938
939 if( X == B )
940 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000942 }
943
944 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200945 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200946
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000947 /*
948 * X should always be positive as a result of unsigned additions.
949 */
950 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000951
Paul Bakker23986e52011-04-24 08:57:21 +0000952 for( j = B->n; j > 0; j-- )
953 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000954 break;
955
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200956 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000957
958 o = B->p; p = X->p; c = 0;
959
Janos Follath6c922682015-10-30 17:43:11 +0100960 /*
961 * tmp is used because it might happen that p == o
962 */
Paul Bakker23986e52011-04-24 08:57:21 +0000963 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000964 {
Janos Follath6c922682015-10-30 17:43:11 +0100965 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000966 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100967 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000968 }
969
970 while( c != 0 )
971 {
972 if( i >= X->n )
973 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200974 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000975 p = X->p + i;
976 }
977
Paul Bakker2d319fd2012-09-16 21:34:26 +0000978 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000979 }
980
981cleanup:
982
983 return( ret );
984}
985
986/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200987 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000988 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200989static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000990{
Paul Bakker23986e52011-04-24 08:57:21 +0000991 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200992 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000993
994 for( i = c = 0; i < n; i++, s++, d++ )
995 {
996 z = ( *d < c ); *d -= c;
997 c = ( *d < *s ) + z; *d -= *s;
998 }
999
1000 while( c != 0 )
1001 {
1002 z = ( *d < c ); *d -= c;
1003 c = z; i++; d++;
1004 }
1005}
1006
1007/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001008 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001009 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001010int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001011{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001012 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001013 int ret;
1014 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001015
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1017 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001018
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001020
1021 if( X == B )
1022 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001023 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001024 B = &TB;
1025 }
1026
1027 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001028 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001029
Paul Bakker1ef7a532009-06-20 10:50:55 +00001030 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001031 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001032 */
1033 X->s = 1;
1034
Paul Bakker5121ce52009-01-03 21:22:43 +00001035 ret = 0;
1036
Paul Bakker23986e52011-04-24 08:57:21 +00001037 for( n = B->n; n > 0; n-- )
1038 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001039 break;
1040
Paul Bakker23986e52011-04-24 08:57:21 +00001041 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001042
1043cleanup:
1044
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001045 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001046
1047 return( ret );
1048}
1049
1050/*
1051 * Signed addition: X = A + B
1052 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001053int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001054{
1055 int ret, s = A->s;
1056
1057 if( A->s * B->s < 0 )
1058 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001059 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001060 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001061 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001062 X->s = s;
1063 }
1064 else
1065 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001066 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001067 X->s = -s;
1068 }
1069 }
1070 else
1071 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001072 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001073 X->s = s;
1074 }
1075
1076cleanup:
1077
1078 return( ret );
1079}
1080
1081/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001082 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001083 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001084int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001085{
1086 int ret, s = A->s;
1087
1088 if( A->s * B->s > 0 )
1089 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001090 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001091 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001092 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001093 X->s = s;
1094 }
1095 else
1096 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001097 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001098 X->s = -s;
1099 }
1100 }
1101 else
1102 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001103 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001104 X->s = s;
1105 }
1106
1107cleanup:
1108
1109 return( ret );
1110}
1111
1112/*
1113 * Signed addition: X = A + b
1114 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001116{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001117 mbedtls_mpi _B;
1118 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001119
1120 p[0] = ( b < 0 ) ? -b : b;
1121 _B.s = ( b < 0 ) ? -1 : 1;
1122 _B.n = 1;
1123 _B.p = p;
1124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001125 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001126}
1127
1128/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001129 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001130 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001131int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001132{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001133 mbedtls_mpi _B;
1134 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001135
1136 p[0] = ( b < 0 ) ? -b : b;
1137 _B.s = ( b < 0 ) ? -1 : 1;
1138 _B.n = 1;
1139 _B.p = p;
1140
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001141 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001142}
1143
1144/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001145 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001146 */
1147static
1148#if defined(__APPLE__) && defined(__arm__)
1149/*
1150 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1151 * appears to need this to prevent bad ARM code generation at -O3.
1152 */
1153__attribute__ ((noinline))
1154#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001155void 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 +00001156{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001157 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001158
1159#if defined(MULADDC_HUIT)
1160 for( ; i >= 8; i -= 8 )
1161 {
1162 MULADDC_INIT
1163 MULADDC_HUIT
1164 MULADDC_STOP
1165 }
1166
1167 for( ; i > 0; i-- )
1168 {
1169 MULADDC_INIT
1170 MULADDC_CORE
1171 MULADDC_STOP
1172 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001173#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001174 for( ; i >= 16; i -= 16 )
1175 {
1176 MULADDC_INIT
1177 MULADDC_CORE MULADDC_CORE
1178 MULADDC_CORE MULADDC_CORE
1179 MULADDC_CORE MULADDC_CORE
1180 MULADDC_CORE MULADDC_CORE
1181
1182 MULADDC_CORE MULADDC_CORE
1183 MULADDC_CORE MULADDC_CORE
1184 MULADDC_CORE MULADDC_CORE
1185 MULADDC_CORE MULADDC_CORE
1186 MULADDC_STOP
1187 }
1188
1189 for( ; i >= 8; i -= 8 )
1190 {
1191 MULADDC_INIT
1192 MULADDC_CORE MULADDC_CORE
1193 MULADDC_CORE MULADDC_CORE
1194
1195 MULADDC_CORE MULADDC_CORE
1196 MULADDC_CORE MULADDC_CORE
1197 MULADDC_STOP
1198 }
1199
1200 for( ; i > 0; i-- )
1201 {
1202 MULADDC_INIT
1203 MULADDC_CORE
1204 MULADDC_STOP
1205 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001206#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001207
1208 t++;
1209
1210 do {
1211 *d += c; c = ( *d < c ); d++;
1212 }
1213 while( c != 0 );
1214}
1215
1216/*
1217 * Baseline multiplication: X = A * B (HAC 14.12)
1218 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001219int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001220{
Paul Bakker23986e52011-04-24 08:57:21 +00001221 int ret;
1222 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001223 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001224
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001225 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001227 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1228 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001229
Paul Bakker23986e52011-04-24 08:57:21 +00001230 for( i = A->n; i > 0; i-- )
1231 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001232 break;
1233
Paul Bakker23986e52011-04-24 08:57:21 +00001234 for( j = B->n; j > 0; j-- )
1235 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001236 break;
1237
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001238 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1239 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001240
Paul Bakker23986e52011-04-24 08:57:21 +00001241 for( i++; j > 0; j-- )
1242 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001243
1244 X->s = A->s * B->s;
1245
1246cleanup:
1247
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001248 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001249
1250 return( ret );
1251}
1252
1253/*
1254 * Baseline multiplication: X = A * b
1255 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001256int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001257{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001258 mbedtls_mpi _B;
1259 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001260
1261 _B.s = 1;
1262 _B.n = 1;
1263 _B.p = p;
1264 p[0] = b;
1265
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001266 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001267}
1268
1269/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001270 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1271 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001272 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001273static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1274 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001275{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001276#if defined(MBEDTLS_HAVE_UDBL)
1277 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001278#else
Simon Butcher9803d072016-01-03 00:24:34 +00001279 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1280 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001281 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1282 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001283 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001284#endif
1285
Simon Butcher15b15d12015-11-26 19:35:03 +00001286 /*
1287 * Check for overflow
1288 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001289 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001290 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001291 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001292
Simon Butcherf5ba0452015-12-27 23:01:55 +00001293 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001294 }
1295
1296#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001297 dividend = (mbedtls_t_udbl) u1 << biL;
1298 dividend |= (mbedtls_t_udbl) u0;
1299 quotient = dividend / d;
1300 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1301 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1302
1303 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001304 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001305
1306 return (mbedtls_mpi_uint) quotient;
1307#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001308
1309 /*
1310 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1311 * Vol. 2 - Seminumerical Algorithms, Knuth
1312 */
1313
1314 /*
1315 * Normalize the divisor, d, and dividend, u0, u1
1316 */
1317 s = mbedtls_clz( d );
1318 d = d << s;
1319
1320 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001321 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001322 u0 = u0 << s;
1323
1324 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001325 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001326
1327 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001328 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001329
1330 /*
1331 * Find the first quotient and remainder
1332 */
1333 q1 = u1 / d1;
1334 r0 = u1 - d1 * q1;
1335
1336 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1337 {
1338 q1 -= 1;
1339 r0 += d1;
1340
1341 if ( r0 >= radix ) break;
1342 }
1343
Simon Butcherf5ba0452015-12-27 23:01:55 +00001344 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001345 q0 = rAX / d1;
1346 r0 = rAX - q0 * d1;
1347
1348 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1349 {
1350 q0 -= 1;
1351 r0 += d1;
1352
1353 if ( r0 >= radix ) break;
1354 }
1355
1356 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001357 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001358
1359 quotient = q1 * radix + q0;
1360
1361 return quotient;
1362#endif
1363}
1364
1365/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001367 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001368int 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 +00001369{
Paul Bakker23986e52011-04-24 08:57:21 +00001370 int ret;
1371 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001373
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001374 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1375 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001376
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001377 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1378 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001379
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001380 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001381 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001382 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1383 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001384 return( 0 );
1385 }
1386
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001387 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1388 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001389 X.s = Y.s = 1;
1390
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1392 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1393 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1394 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001395
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001396 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001397 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001398 {
1399 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1401 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001402 }
1403 else k = 0;
1404
1405 n = X.n - 1;
1406 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001407 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001409 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001410 {
1411 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001412 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001413 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001415
1416 for( i = n; i > t ; i-- )
1417 {
1418 if( X.p[i] >= Y.p[t] )
1419 Z.p[i - t - 1] = ~0;
1420 else
1421 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001422 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1423 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001424 }
1425
1426 Z.p[i - t - 1]++;
1427 do
1428 {
1429 Z.p[i - t - 1]--;
1430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001431 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001432 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001433 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001434 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001435
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001436 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001437 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1438 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001439 T2.p[2] = X.p[i];
1440 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001441 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001443 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1444 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1445 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001446
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001447 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001448 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001449 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1450 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1451 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001452 Z.p[i - t - 1]--;
1453 }
1454 }
1455
1456 if( Q != NULL )
1457 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001458 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001459 Q->s = A->s * B->s;
1460 }
1461
1462 if( R != NULL )
1463 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001464 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001465 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001468 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001469 R->s = 1;
1470 }
1471
1472cleanup:
1473
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001474 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1475 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001476
1477 return( ret );
1478}
1479
1480/*
1481 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001482 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001483int 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 +00001484{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001485 mbedtls_mpi _B;
1486 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001487
1488 p[0] = ( b < 0 ) ? -b : b;
1489 _B.s = ( b < 0 ) ? -1 : 1;
1490 _B.n = 1;
1491 _B.p = p;
1492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001493 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001494}
1495
1496/*
1497 * Modulo: R = A mod B
1498 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001499int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001500{
1501 int ret;
1502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001503 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1504 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001505
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001508 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1509 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1512 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001513
1514cleanup:
1515
1516 return( ret );
1517}
1518
1519/*
1520 * Modulo: r = A mod b
1521 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001522int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001523{
Paul Bakker23986e52011-04-24 08:57:21 +00001524 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001525 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001526
1527 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001528 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001529
1530 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001531 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001532
1533 /*
1534 * handle trivial cases
1535 */
1536 if( b == 1 )
1537 {
1538 *r = 0;
1539 return( 0 );
1540 }
1541
1542 if( b == 2 )
1543 {
1544 *r = A->p[0] & 1;
1545 return( 0 );
1546 }
1547
1548 /*
1549 * general case
1550 */
Paul Bakker23986e52011-04-24 08:57:21 +00001551 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001552 {
Paul Bakker23986e52011-04-24 08:57:21 +00001553 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001554 y = ( y << biH ) | ( x >> biH );
1555 z = y / b;
1556 y -= z * b;
1557
1558 x <<= biH;
1559 y = ( y << biH ) | ( x >> biH );
1560 z = y / b;
1561 y -= z * b;
1562 }
1563
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001564 /*
1565 * If A is negative, then the current y represents a negative value.
1566 * Flipping it to the positive side.
1567 */
1568 if( A->s < 0 && y != 0 )
1569 y = b - y;
1570
Paul Bakker5121ce52009-01-03 21:22:43 +00001571 *r = y;
1572
1573 return( 0 );
1574}
1575
1576/*
1577 * Fast Montgomery initialization (thanks to Tom St Denis)
1578 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001579static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001580{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001581 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001582 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001583
1584 x = m0;
1585 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001586
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001587 for( i = biL; i >= 8; i /= 2 )
1588 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001589
1590 *mm = ~x + 1;
1591}
1592
1593/*
1594 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1595 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001596static 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 +02001597 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001598{
Paul Bakker23986e52011-04-24 08:57:21 +00001599 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001600 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001601
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001602 if( T->n < N->n + 1 || T->p == NULL )
1603 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1604
Paul Bakker5121ce52009-01-03 21:22:43 +00001605 memset( T->p, 0, T->n * ciL );
1606
1607 d = T->p;
1608 n = N->n;
1609 m = ( B->n < n ) ? B->n : n;
1610
1611 for( i = 0; i < n; i++ )
1612 {
1613 /*
1614 * T = (T + u0*B + u1*N) / 2^biL
1615 */
1616 u0 = A->p[i];
1617 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1618
1619 mpi_mul_hlp( m, B->p, d, u0 );
1620 mpi_mul_hlp( n, N->p, d, u1 );
1621
1622 *d++ = u0; d[n + 1] = 0;
1623 }
1624
Paul Bakker66d5d072014-06-17 16:39:18 +02001625 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001627 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001628 mpi_sub_hlp( n, N->p, A->p );
1629 else
1630 /* prevent timing attacks */
1631 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001632
1633 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001634}
1635
1636/*
1637 * Montgomery reduction: A = A * R^-1 mod N
1638 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001639static 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 +00001640{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001641 mbedtls_mpi_uint z = 1;
1642 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001643
Paul Bakker8ddb6452013-02-27 14:56:33 +01001644 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001645 U.p = &z;
1646
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001647 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001648}
1649
1650/*
1651 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1652 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001653int 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 +00001654{
Paul Bakker23986e52011-04-24 08:57:21 +00001655 int ret;
1656 size_t wbits, wsize, one = 1;
1657 size_t i, j, nblimbs;
1658 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001659 mbedtls_mpi_uint ei, mm, state;
1660 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001661 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001662
Hanno Becker930ec7d2018-03-09 10:48:00 +00001663 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001664 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001665
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001666 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1667 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001668
1669 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001670 * Init temps and window size
1671 */
1672 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001673 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1674 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001675 memset( W, 0, sizeof( W ) );
1676
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001677 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001678
1679 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1680 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1681
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001682#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001683 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1684 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001685#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001686
Paul Bakker5121ce52009-01-03 21:22:43 +00001687 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1689 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1690 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001691
1692 /*
Paul Bakker50546922012-05-19 08:40:49 +00001693 * Compensate for negative A (and correct at the end)
1694 */
1695 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001696 if( neg )
1697 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001698 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001699 Apos.s = 1;
1700 A = &Apos;
1701 }
1702
1703 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001704 * If 1st call, pre-compute R^2 mod N
1705 */
1706 if( _RR == NULL || _RR->p == NULL )
1707 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001708 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1709 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1710 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001711
1712 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001713 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001714 }
1715 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001716 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001717
1718 /*
1719 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1720 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001721 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1722 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001723 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001724 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001725
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001726 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001727
1728 /*
1729 * X = R^2 * R^-1 mod N = R mod N
1730 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001731 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001732 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001733
1734 if( wsize > 1 )
1735 {
1736 /*
1737 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1738 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001739 j = one << ( wsize - 1 );
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[j], N->n + 1 ) );
1742 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001743
1744 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001745 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001746
Paul Bakker5121ce52009-01-03 21:22:43 +00001747 /*
1748 * W[i] = W[i - 1] * W[1]
1749 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001750 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001751 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001752 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1753 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001754
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001755 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001756 }
1757 }
1758
1759 nblimbs = E->n;
1760 bufsize = 0;
1761 nbits = 0;
1762 wbits = 0;
1763 state = 0;
1764
1765 while( 1 )
1766 {
1767 if( bufsize == 0 )
1768 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001769 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001770 break;
1771
Paul Bakker0d7702c2013-10-29 16:18:35 +01001772 nblimbs--;
1773
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001774 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001775 }
1776
1777 bufsize--;
1778
1779 ei = (E->p[nblimbs] >> bufsize) & 1;
1780
1781 /*
1782 * skip leading 0s
1783 */
1784 if( ei == 0 && state == 0 )
1785 continue;
1786
1787 if( ei == 0 && state == 1 )
1788 {
1789 /*
1790 * out of window, square X
1791 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001792 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001793 continue;
1794 }
1795
1796 /*
1797 * add ei to current window
1798 */
1799 state = 2;
1800
1801 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001802 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001803
1804 if( nbits == wsize )
1805 {
1806 /*
1807 * X = X^wsize R^-1 mod N
1808 */
1809 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001810 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001811
1812 /*
1813 * X = X * W[wbits] R^-1 mod N
1814 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001815 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001816
1817 state--;
1818 nbits = 0;
1819 wbits = 0;
1820 }
1821 }
1822
1823 /*
1824 * process the remaining bits
1825 */
1826 for( i = 0; i < nbits; i++ )
1827 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001828 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001829
1830 wbits <<= 1;
1831
Paul Bakker66d5d072014-06-17 16:39:18 +02001832 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001833 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001834 }
1835
1836 /*
1837 * X = A^E * R * R^-1 mod N = A^E mod N
1838 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001839 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001840
Hanno Beckera4af1c42017-04-18 09:07:45 +01001841 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001842 {
1843 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001845 }
1846
Paul Bakker5121ce52009-01-03 21:22:43 +00001847cleanup:
1848
Paul Bakker66d5d072014-06-17 16:39:18 +02001849 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001850 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001851
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001852 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001853
Paul Bakker75a28602014-03-31 12:08:17 +02001854 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001855 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001856
1857 return( ret );
1858}
1859
Paul Bakker5121ce52009-01-03 21:22:43 +00001860/*
1861 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1862 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001863int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001864{
Paul Bakker23986e52011-04-24 08:57:21 +00001865 int ret;
1866 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001867 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001868
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001869 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001870
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001871 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1872 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001873
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001874 lz = mbedtls_mpi_lsb( &TA );
1875 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001876
Paul Bakker66d5d072014-06-17 16:39:18 +02001877 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001878 lz = lzt;
1879
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1881 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001882
Paul Bakker5121ce52009-01-03 21:22:43 +00001883 TA.s = TB.s = 1;
1884
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001885 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001886 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001887 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1888 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001889
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001890 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001891 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001892 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1893 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001894 }
1895 else
1896 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001897 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1898 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001899 }
1900 }
1901
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001902 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1903 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001904
1905cleanup:
1906
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001907 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001908
1909 return( ret );
1910}
1911
Paul Bakker33dc46b2014-04-30 16:11:39 +02001912/*
1913 * Fill X with size bytes of random.
1914 *
1915 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001916 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001917 * deterministic, eg for tests).
1918 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001919int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001920 int (*f_rng)(void *, unsigned char *, size_t),
1921 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001922{
Paul Bakker23986e52011-04-24 08:57:21 +00001923 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001924 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001925
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001926 if( size > MBEDTLS_MPI_MAX_SIZE )
1927 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001928
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1930 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001931
1932cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01001933 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001934 return( ret );
1935}
1936
Paul Bakker5121ce52009-01-03 21:22:43 +00001937/*
1938 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1939 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001940int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001941{
1942 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001943 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001944
Hanno Becker4bcb4912017-04-18 15:49:39 +01001945 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001946 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001947
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001948 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1949 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1950 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001951
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001952 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001953
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001954 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001955 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001956 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001957 goto cleanup;
1958 }
1959
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001960 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1961 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1962 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1963 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001964
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001965 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1966 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1967 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1968 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
1970 do
1971 {
1972 while( ( TU.p[0] & 1 ) == 0 )
1973 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001974 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001975
1976 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1977 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001978 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1979 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001980 }
1981
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001982 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1983 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001984 }
1985
1986 while( ( TV.p[0] & 1 ) == 0 )
1987 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001989
1990 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1991 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001992 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1993 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001994 }
1995
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001996 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1997 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001998 }
1999
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002000 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002001 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002002 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2003 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2004 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002005 }
2006 else
2007 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002008 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2009 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2010 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002011 }
2012 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002013 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002014
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002015 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2016 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002017
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002018 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2019 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002020
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002021 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
2023cleanup:
2024
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002025 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2026 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2027 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002028
2029 return( ret );
2030}
2031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002032#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002033
Paul Bakker5121ce52009-01-03 21:22:43 +00002034static const int small_prime[] =
2035{
2036 3, 5, 7, 11, 13, 17, 19, 23,
2037 29, 31, 37, 41, 43, 47, 53, 59,
2038 61, 67, 71, 73, 79, 83, 89, 97,
2039 101, 103, 107, 109, 113, 127, 131, 137,
2040 139, 149, 151, 157, 163, 167, 173, 179,
2041 181, 191, 193, 197, 199, 211, 223, 227,
2042 229, 233, 239, 241, 251, 257, 263, 269,
2043 271, 277, 281, 283, 293, 307, 311, 313,
2044 317, 331, 337, 347, 349, 353, 359, 367,
2045 373, 379, 383, 389, 397, 401, 409, 419,
2046 421, 431, 433, 439, 443, 449, 457, 461,
2047 463, 467, 479, 487, 491, 499, 503, 509,
2048 521, 523, 541, 547, 557, 563, 569, 571,
2049 577, 587, 593, 599, 601, 607, 613, 617,
2050 619, 631, 641, 643, 647, 653, 659, 661,
2051 673, 677, 683, 691, 701, 709, 719, 727,
2052 733, 739, 743, 751, 757, 761, 769, 773,
2053 787, 797, 809, 811, 821, 823, 827, 829,
2054 839, 853, 857, 859, 863, 877, 881, 883,
2055 887, 907, 911, 919, 929, 937, 941, 947,
2056 953, 967, 971, 977, 983, 991, 997, -103
2057};
2058
2059/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002060 * Small divisors test (X must be positive)
2061 *
2062 * Return values:
2063 * 0: no small factor (possible prime, more tests needed)
2064 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002065 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002066 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002067 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002068static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002069{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002070 int ret = 0;
2071 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002072 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002073
Paul Bakker5121ce52009-01-03 21:22:43 +00002074 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002075 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002076
2077 for( i = 0; small_prime[i] > 0; i++ )
2078 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002079 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002080 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002081
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002082 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002083
2084 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002085 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002086 }
2087
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002088cleanup:
2089 return( ret );
2090}
2091
2092/*
2093 * Miller-Rabin pseudo-primality test (HAC 4.24)
2094 */
Janos Follath72d555d2018-09-03 14:45:23 +01002095static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002096 int (*f_rng)(void *, unsigned char *, size_t),
2097 void *p_rng )
2098{
Pascal Junodb99183d2015-03-11 16:49:45 +01002099 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002100 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002101 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002102
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002103 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2104 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002105
Paul Bakker5121ce52009-01-03 21:22:43 +00002106 /*
2107 * W = |X| - 1
2108 * R = W >> lsb( W )
2109 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002110 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2111 s = mbedtls_mpi_lsb( &W );
2112 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2113 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002114
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002115 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002116
Janos Follath72d555d2018-09-03 14:45:23 +01002117 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002118 {
2119 /*
2120 * pick a random A, 1 < A < |X| - 1
2121 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002122 count = 0;
2123 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002124 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002125
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002126 j = mbedtls_mpi_bitlen( &A );
2127 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002128 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002129 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002130 }
2131
2132 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002133 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002134 }
2135
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002136 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2137 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002138
2139 /*
2140 * A = A^R mod |X|
2141 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002142 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002143
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002144 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2145 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002146 continue;
2147
2148 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002149 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002150 {
2151 /*
2152 * A = A * A mod |X|
2153 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002154 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2155 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002156
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002157 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002158 break;
2159
2160 j++;
2161 }
2162
2163 /*
2164 * not prime if A != |X| - 1 or A == 1
2165 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002166 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2167 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002168 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002169 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002170 break;
2171 }
2172 }
2173
2174cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002175 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2176 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002177
2178 return( ret );
2179}
2180
2181/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002182 * Pseudo-primality test: small factors, then Miller-Rabin
2183 */
Darryl Green94759f62018-10-16 15:09:19 +01002184static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002185 int (*f_rng)(void *, unsigned char *, size_t),
2186 void *p_rng )
2187{
2188 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002189 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002190
2191 XX.s = 1;
2192 XX.n = X->n;
2193 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002194
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002195 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2196 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2197 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002198
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002199 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002200 return( 0 );
2201
2202 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2203 {
2204 if( ret == 1 )
2205 return( 0 );
2206
2207 return( ret );
2208 }
2209
Janos Follath72d555d2018-09-03 14:45:23 +01002210 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2211}
2212
2213/*
2214 * Pseudo-primality test, error probability 2^-80
2215 */
2216int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2217 int (*f_rng)(void *, unsigned char *, size_t),
2218 void *p_rng )
2219{
2220 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002221}
2222
2223/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002224 * Prime number generation
2225 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002226int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
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{
Paul Bakker23986e52011-04-24 08:57:21 +00002230 int ret;
2231 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002232 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002233 mbedtls_mpi_uint r;
2234 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002235
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002236 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2237 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002239 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002240
2241 n = BITS_TO_LIMBS( nbits );
2242
Janos Follath72d555d2018-09-03 14:45:23 +01002243 /*
2244 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2245 */
2246 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2247 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2248 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2249
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002250 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002251
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002252 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002253 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002254
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002255 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002256
2257 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002258
2259 if( dh_flag == 0 )
2260 {
Janos Follath72d555d2018-09-03 14:45:23 +01002261 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002262 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002263 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002264 goto cleanup;
2265
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002266 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002267 }
2268 }
2269 else
2270 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002271 /*
2272 * An necessary condition for Y and X = 2Y + 1 to be prime
2273 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2274 * Make sure it is satisfied, while keeping X = 3 mod 4
2275 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002276
2277 X->p[0] |= 2;
2278
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002279 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002280 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002281 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002282 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002283 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002284
2285 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002286 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2287 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002288
2289 while( 1 )
2290 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002291 /*
2292 * First, check small factors for X and Y
2293 * before doing Miller-Rabin on any of them
2294 */
2295 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2296 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002297 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2298 == 0 &&
2299 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2300 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002301 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002302 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002303 }
2304
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002305 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002306 goto cleanup;
2307
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002308 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002309 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002310 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2311 * so up Y by 6 and X by 12.
2312 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002313 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2314 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002315 }
2316 }
2317
2318cleanup:
2319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002320 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002321
2322 return( ret );
2323}
2324
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002325#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002327#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002328
Paul Bakker23986e52011-04-24 08:57:21 +00002329#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002330
2331static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2332{
2333 { 693, 609, 21 },
2334 { 1764, 868, 28 },
2335 { 768454923, 542167814, 1 }
2336};
2337
Paul Bakker5121ce52009-01-03 21:22:43 +00002338/*
2339 * Checkup routine
2340 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002342{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002343 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002344 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002346 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2347 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002349 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002350 "EFE021C2645FD1DC586E69184AF4A31E" \
2351 "D5F53E93B5F123FA41680867BA110131" \
2352 "944FE7952E2517337780CB0DB80E61AA" \
2353 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2354
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002355 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002356 "B2E7EFD37075B9F03FF989C7C5051C20" \
2357 "34D2A323810251127E7BF8625A4F49A5" \
2358 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2359 "5B5C25763222FEFCCFC38B832366C29E" ) );
2360
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002361 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002362 "0066A198186C18C10B2F5ED9B522752A" \
2363 "9830B69916E535C8F047518A889A43A5" \
2364 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002366 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002367
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002368 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002369 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2370 "9E857EA95A03512E2BAE7391688D264A" \
2371 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2372 "8001B72E848A38CAE1C65F78E56ABDEF" \
2373 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2374 "ECF677152EF804370C1A305CAF3B5BF1" \
2375 "30879B56C61DE584A0F53A2447A51E" ) );
2376
2377 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002378 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002379
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002380 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002381 {
2382 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002384
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002385 ret = 1;
2386 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002387 }
2388
2389 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002390 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002392 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002393
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002394 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002395 "256567336059E52CAE22925474705F39A94" ) );
2396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002397 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002398 "6613F26162223DF488E9CD48CC132C7A" \
2399 "0AC93C701B001B092E4E5B9F73BCD27B" \
2400 "9EE50D0657C77F374E903CDFA4C642" ) );
2401
2402 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002403 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002404
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002405 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2406 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002407 {
2408 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002409 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002410
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002411 ret = 1;
2412 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002413 }
2414
2415 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002416 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002417
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002418 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002419
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002420 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002421 "36E139AEA55215609D2816998ED020BB" \
2422 "BD96C37890F65171D948E9BC7CBAA4D9" \
2423 "325D24D6A3C12710F10A09FA08AB87" ) );
2424
2425 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002426 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002427
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002428 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002429 {
2430 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002431 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002432
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002433 ret = 1;
2434 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002435 }
2436
2437 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002438 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002439
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002441
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002442 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002443 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2444 "C3DBA76456363A10869622EAC2DD84EC" \
2445 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2446
2447 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002448 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002449
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002450 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002451 {
2452 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002453 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002454
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002455 ret = 1;
2456 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002457 }
2458
2459 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002460 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002461
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002462 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002463 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002464
Paul Bakker66d5d072014-06-17 16:39:18 +02002465 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002466 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002467 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2468 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002469
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002470 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002472 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002473 {
2474 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002476
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002477 ret = 1;
2478 goto cleanup;
2479 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002480 }
2481
2482 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002483 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002484
Paul Bakker5121ce52009-01-03 21:22:43 +00002485cleanup:
2486
2487 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002488 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002489
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002490 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2491 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002492
2493 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002494 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002495
2496 return( ret );
2497}
2498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002499#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002500
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002501#endif /* MBEDTLS_BIGNUM_C */