blob: 54ab7e3ec5c4d1a265cb172b49fa9d98f6acf97e [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 )
Hanno Beckereff335d2019-02-01 16:41:30 +0000575 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000576 *p++ = '-';
Hanno Beckereff335d2019-02-01 16:41:30 +0000577 buflen--;
578 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000579
580 if( radix == 16 )
581 {
Paul Bakker23986e52011-04-24 08:57:21 +0000582 int c;
583 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
Paul Bakker23986e52011-04-24 08:57:21 +0000585 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000586 {
Paul Bakker23986e52011-04-24 08:57:21 +0000587 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000588 {
Paul Bakker23986e52011-04-24 08:57:21 +0000589 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000590
Paul Bakker6c343d72014-07-10 14:36:19 +0200591 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000592 continue;
593
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000594 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000595 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000596 k = 1;
597 }
598 }
599 }
600 else
601 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000603
604 if( T.s == -1 )
605 T.s = 1;
606
Ron Eldore6cbfc32018-11-20 14:07:01 +0200607 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000608 }
609
610 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100611 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000612
613cleanup:
614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200615 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000616
617 return( ret );
618}
619
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000621/*
622 * Read X from an opened file
623 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200624int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000625{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200626 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000627 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000628 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000629 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000630 * Buffer should have space for (short) label and decimal formatted MPI,
631 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000632 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200633 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000634
635 memset( s, 0, sizeof( s ) );
636 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000638
639 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000640 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000642
Hanno Beckerb2034b72017-04-26 11:46:46 +0100643 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
644 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000645
646 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100647 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000648 if( mpi_get_digit( &d, radix, *p ) != 0 )
649 break;
650
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000652}
653
654/*
655 * Write X into an opened file (or stdout if fout == NULL)
656 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200657int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000658{
Paul Bakker23986e52011-04-24 08:57:21 +0000659 int ret;
660 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000661 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000662 * Buffer should have space for (short) label and decimal formatted MPI,
663 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000664 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000666
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100667 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000668
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100669 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000670
671 if( p == NULL ) p = "";
672
673 plen = strlen( p );
674 slen = strlen( s );
675 s[slen++] = '\r';
676 s[slen++] = '\n';
677
678 if( fout != NULL )
679 {
680 if( fwrite( p, 1, plen, fout ) != plen ||
681 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000683 }
684 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000686
687cleanup:
688
689 return( ret );
690}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000692
693/*
694 * Import X from unsigned binary data, big endian
695 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000697{
Paul Bakker23986e52011-04-24 08:57:21 +0000698 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100699 size_t i, j;
700 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000701
Hanno Becker073c1992017-10-17 15:17:27 +0100702 /* Ensure that target MPI has exactly the necessary number of limbs */
703 if( X->n != limbs )
704 {
705 mbedtls_mpi_free( X );
706 mbedtls_mpi_init( X );
707 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
708 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000709
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
Hanno Becker073c1992017-10-17 15:17:27 +0100712 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200713 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000714
715cleanup:
716
717 return( ret );
718}
719
720/*
721 * Export X into unsigned binary data, big endian
722 */
Gilles Peskine220cc172018-11-20 16:47:47 +0100723int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
724 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000725{
Gilles Peskine220cc172018-11-20 16:47:47 +0100726 size_t stored_bytes = X->n * ciL;
727 size_t bytes_to_copy;
728 unsigned char *p;
729 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000730
Gilles Peskine220cc172018-11-20 16:47:47 +0100731 if( stored_bytes < buflen )
732 {
733 /* There is enough space in the output buffer. Write initial
734 * null bytes and record the position at which to start
735 * writing the significant bytes. In this case, the execution
736 * trace of this function does not depend on the value of the
737 * number. */
738 bytes_to_copy = stored_bytes;
739 p = buf + buflen - stored_bytes;
740 memset( buf, 0, buflen - stored_bytes );
741 }
742 else
743 {
744 /* The output buffer is smaller than the allocated size of X.
745 * However X may fit if its leading bytes are zero. */
746 bytes_to_copy = buflen;
747 p = buf;
748 for( i = bytes_to_copy; i < stored_bytes; i++ )
749 {
750 if( GET_BYTE( X, i ) != 0 )
751 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
752 }
753 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000754
Gilles Peskine220cc172018-11-20 16:47:47 +0100755 for( i = 0; i < bytes_to_copy; i++ )
756 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000757
758 return( 0 );
759}
760
761/*
762 * Left-shift: X <<= count
763 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200764int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000765{
Paul Bakker23986e52011-04-24 08:57:21 +0000766 int ret;
767 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200768 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000769
770 v0 = count / (biL );
771 t1 = count & (biL - 1);
772
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200773 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000774
Paul Bakkerf9688572011-05-05 10:00:45 +0000775 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200776 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000777
778 ret = 0;
779
780 /*
781 * shift by count / limb_size
782 */
783 if( v0 > 0 )
784 {
Paul Bakker23986e52011-04-24 08:57:21 +0000785 for( i = X->n; i > v0; i-- )
786 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000787
Paul Bakker23986e52011-04-24 08:57:21 +0000788 for( ; i > 0; i-- )
789 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000790 }
791
792 /*
793 * shift by count % limb_size
794 */
795 if( t1 > 0 )
796 {
797 for( i = v0; i < X->n; i++ )
798 {
799 r1 = X->p[i] >> (biL - t1);
800 X->p[i] <<= t1;
801 X->p[i] |= r0;
802 r0 = r1;
803 }
804 }
805
806cleanup:
807
808 return( ret );
809}
810
811/*
812 * Right-shift: X >>= count
813 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200814int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000815{
Paul Bakker23986e52011-04-24 08:57:21 +0000816 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200817 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000818
819 v0 = count / biL;
820 v1 = count & (biL - 1);
821
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100822 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200823 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100824
Paul Bakker5121ce52009-01-03 21:22:43 +0000825 /*
826 * shift by count / limb_size
827 */
828 if( v0 > 0 )
829 {
830 for( i = 0; i < X->n - v0; i++ )
831 X->p[i] = X->p[i + v0];
832
833 for( ; i < X->n; i++ )
834 X->p[i] = 0;
835 }
836
837 /*
838 * shift by count % limb_size
839 */
840 if( v1 > 0 )
841 {
Paul Bakker23986e52011-04-24 08:57:21 +0000842 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000843 {
Paul Bakker23986e52011-04-24 08:57:21 +0000844 r1 = X->p[i - 1] << (biL - v1);
845 X->p[i - 1] >>= v1;
846 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000847 r0 = r1;
848 }
849 }
850
851 return( 0 );
852}
853
854/*
855 * Compare unsigned values
856 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200857int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000858{
Paul Bakker23986e52011-04-24 08:57:21 +0000859 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000860
Paul Bakker23986e52011-04-24 08:57:21 +0000861 for( i = X->n; i > 0; i-- )
862 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000863 break;
864
Paul Bakker23986e52011-04-24 08:57:21 +0000865 for( j = Y->n; j > 0; j-- )
866 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000867 break;
868
Paul Bakker23986e52011-04-24 08:57:21 +0000869 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000870 return( 0 );
871
872 if( i > j ) return( 1 );
873 if( j > i ) return( -1 );
874
Paul Bakker23986e52011-04-24 08:57:21 +0000875 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000876 {
Paul Bakker23986e52011-04-24 08:57:21 +0000877 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
878 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000879 }
880
881 return( 0 );
882}
883
884/*
885 * Compare signed values
886 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200887int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000888{
Paul Bakker23986e52011-04-24 08:57:21 +0000889 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000890
Paul Bakker23986e52011-04-24 08:57:21 +0000891 for( i = X->n; i > 0; i-- )
892 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000893 break;
894
Paul Bakker23986e52011-04-24 08:57:21 +0000895 for( j = Y->n; j > 0; j-- )
896 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000897 break;
898
Paul Bakker23986e52011-04-24 08:57:21 +0000899 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000900 return( 0 );
901
902 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000903 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000904
905 if( X->s > 0 && Y->s < 0 ) return( 1 );
906 if( Y->s > 0 && X->s < 0 ) return( -1 );
907
Paul Bakker23986e52011-04-24 08:57:21 +0000908 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000909 {
Paul Bakker23986e52011-04-24 08:57:21 +0000910 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
911 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000912 }
913
914 return( 0 );
915}
916
917/*
918 * Compare signed values
919 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200920int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000921{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200922 mbedtls_mpi Y;
923 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000924
925 *p = ( z < 0 ) ? -z : z;
926 Y.s = ( z < 0 ) ? -1 : 1;
927 Y.n = 1;
928 Y.p = p;
929
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200930 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000931}
932
933/*
934 * Unsigned addition: X = |A| + |B| (HAC 14.7)
935 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200936int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000937{
Paul Bakker23986e52011-04-24 08:57:21 +0000938 int ret;
939 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100940 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000941
942 if( X == B )
943 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200944 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000945 }
946
947 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200948 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200949
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000950 /*
951 * X should always be positive as a result of unsigned additions.
952 */
953 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000954
Paul Bakker23986e52011-04-24 08:57:21 +0000955 for( j = B->n; j > 0; j-- )
956 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000957 break;
958
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200959 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000960
961 o = B->p; p = X->p; c = 0;
962
Janos Follath6c922682015-10-30 17:43:11 +0100963 /*
964 * tmp is used because it might happen that p == o
965 */
Paul Bakker23986e52011-04-24 08:57:21 +0000966 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000967 {
Janos Follath6c922682015-10-30 17:43:11 +0100968 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000969 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100970 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000971 }
972
973 while( c != 0 )
974 {
975 if( i >= X->n )
976 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000978 p = X->p + i;
979 }
980
Paul Bakker2d319fd2012-09-16 21:34:26 +0000981 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000982 }
983
984cleanup:
985
986 return( ret );
987}
988
989/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200990 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000991 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200992static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000993{
Paul Bakker23986e52011-04-24 08:57:21 +0000994 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200995 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000996
997 for( i = c = 0; i < n; i++, s++, d++ )
998 {
999 z = ( *d < c ); *d -= c;
1000 c = ( *d < *s ) + z; *d -= *s;
1001 }
1002
1003 while( c != 0 )
1004 {
1005 z = ( *d < c ); *d -= c;
1006 c = z; i++; d++;
1007 }
1008}
1009
1010/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001011 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001012 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001013int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001014{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001015 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001016 int ret;
1017 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001018
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1020 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001021
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001022 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001023
1024 if( X == B )
1025 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001026 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001027 B = &TB;
1028 }
1029
1030 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001031 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001032
Paul Bakker1ef7a532009-06-20 10:50:55 +00001033 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001034 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001035 */
1036 X->s = 1;
1037
Paul Bakker5121ce52009-01-03 21:22:43 +00001038 ret = 0;
1039
Paul Bakker23986e52011-04-24 08:57:21 +00001040 for( n = B->n; n > 0; n-- )
1041 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001042 break;
1043
Paul Bakker23986e52011-04-24 08:57:21 +00001044 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001045
1046cleanup:
1047
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001048 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001049
1050 return( ret );
1051}
1052
1053/*
1054 * Signed addition: X = A + B
1055 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001056int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001057{
1058 int ret, s = A->s;
1059
1060 if( A->s * B->s < 0 )
1061 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001062 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001063 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001064 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001065 X->s = s;
1066 }
1067 else
1068 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001069 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001070 X->s = -s;
1071 }
1072 }
1073 else
1074 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001075 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001076 X->s = s;
1077 }
1078
1079cleanup:
1080
1081 return( ret );
1082}
1083
1084/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001085 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001086 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001087int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001088{
1089 int ret, s = A->s;
1090
1091 if( A->s * B->s > 0 )
1092 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001093 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001094 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001095 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001096 X->s = s;
1097 }
1098 else
1099 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001100 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001101 X->s = -s;
1102 }
1103 }
1104 else
1105 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001106 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001107 X->s = s;
1108 }
1109
1110cleanup:
1111
1112 return( ret );
1113}
1114
1115/*
1116 * Signed addition: X = A + b
1117 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001118int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001119{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001120 mbedtls_mpi _B;
1121 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001122
1123 p[0] = ( b < 0 ) ? -b : b;
1124 _B.s = ( b < 0 ) ? -1 : 1;
1125 _B.n = 1;
1126 _B.p = p;
1127
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001128 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001129}
1130
1131/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001132 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001133 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001134int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001135{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001136 mbedtls_mpi _B;
1137 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001138
1139 p[0] = ( b < 0 ) ? -b : b;
1140 _B.s = ( b < 0 ) ? -1 : 1;
1141 _B.n = 1;
1142 _B.p = p;
1143
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001144 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001145}
1146
1147/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001148 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001149 */
1150static
1151#if defined(__APPLE__) && defined(__arm__)
1152/*
1153 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1154 * appears to need this to prevent bad ARM code generation at -O3.
1155 */
1156__attribute__ ((noinline))
1157#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001158void 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 +00001159{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001160 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001161
1162#if defined(MULADDC_HUIT)
1163 for( ; i >= 8; i -= 8 )
1164 {
1165 MULADDC_INIT
1166 MULADDC_HUIT
1167 MULADDC_STOP
1168 }
1169
1170 for( ; i > 0; i-- )
1171 {
1172 MULADDC_INIT
1173 MULADDC_CORE
1174 MULADDC_STOP
1175 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001176#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001177 for( ; i >= 16; i -= 16 )
1178 {
1179 MULADDC_INIT
1180 MULADDC_CORE MULADDC_CORE
1181 MULADDC_CORE MULADDC_CORE
1182 MULADDC_CORE MULADDC_CORE
1183 MULADDC_CORE MULADDC_CORE
1184
1185 MULADDC_CORE MULADDC_CORE
1186 MULADDC_CORE MULADDC_CORE
1187 MULADDC_CORE MULADDC_CORE
1188 MULADDC_CORE MULADDC_CORE
1189 MULADDC_STOP
1190 }
1191
1192 for( ; i >= 8; i -= 8 )
1193 {
1194 MULADDC_INIT
1195 MULADDC_CORE MULADDC_CORE
1196 MULADDC_CORE MULADDC_CORE
1197
1198 MULADDC_CORE MULADDC_CORE
1199 MULADDC_CORE MULADDC_CORE
1200 MULADDC_STOP
1201 }
1202
1203 for( ; i > 0; i-- )
1204 {
1205 MULADDC_INIT
1206 MULADDC_CORE
1207 MULADDC_STOP
1208 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001209#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001210
1211 t++;
1212
1213 do {
1214 *d += c; c = ( *d < c ); d++;
1215 }
1216 while( c != 0 );
1217}
1218
1219/*
1220 * Baseline multiplication: X = A * B (HAC 14.12)
1221 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001222int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001223{
Paul Bakker23986e52011-04-24 08:57:21 +00001224 int ret;
1225 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001226 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001227
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001228 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001229
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001230 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1231 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001232
Paul Bakker23986e52011-04-24 08:57:21 +00001233 for( i = A->n; i > 0; i-- )
1234 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001235 break;
1236
Paul Bakker23986e52011-04-24 08:57:21 +00001237 for( j = B->n; j > 0; j-- )
1238 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001239 break;
1240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001241 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1242 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001243
Paul Bakker23986e52011-04-24 08:57:21 +00001244 for( i++; j > 0; j-- )
1245 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001246
1247 X->s = A->s * B->s;
1248
1249cleanup:
1250
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001251 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001252
1253 return( ret );
1254}
1255
1256/*
1257 * Baseline multiplication: X = A * b
1258 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001259int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001260{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001261 mbedtls_mpi _B;
1262 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001263
1264 _B.s = 1;
1265 _B.n = 1;
1266 _B.p = p;
1267 p[0] = b;
1268
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001269 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001270}
1271
1272/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001273 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1274 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001275 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001276static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1277 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001278{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001279#if defined(MBEDTLS_HAVE_UDBL)
1280 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001281#else
Simon Butcher9803d072016-01-03 00:24:34 +00001282 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1283 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001284 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1285 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001286 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001287#endif
1288
Simon Butcher15b15d12015-11-26 19:35:03 +00001289 /*
1290 * Check for overflow
1291 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001292 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001293 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001294 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001295
Simon Butcherf5ba0452015-12-27 23:01:55 +00001296 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001297 }
1298
1299#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001300 dividend = (mbedtls_t_udbl) u1 << biL;
1301 dividend |= (mbedtls_t_udbl) u0;
1302 quotient = dividend / d;
1303 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1304 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1305
1306 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001307 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001308
1309 return (mbedtls_mpi_uint) quotient;
1310#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001311
1312 /*
1313 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1314 * Vol. 2 - Seminumerical Algorithms, Knuth
1315 */
1316
1317 /*
1318 * Normalize the divisor, d, and dividend, u0, u1
1319 */
1320 s = mbedtls_clz( d );
1321 d = d << s;
1322
1323 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001324 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001325 u0 = u0 << s;
1326
1327 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001328 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001329
1330 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001331 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001332
1333 /*
1334 * Find the first quotient and remainder
1335 */
1336 q1 = u1 / d1;
1337 r0 = u1 - d1 * q1;
1338
1339 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1340 {
1341 q1 -= 1;
1342 r0 += d1;
1343
1344 if ( r0 >= radix ) break;
1345 }
1346
Simon Butcherf5ba0452015-12-27 23:01:55 +00001347 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001348 q0 = rAX / d1;
1349 r0 = rAX - q0 * d1;
1350
1351 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1352 {
1353 q0 -= 1;
1354 r0 += d1;
1355
1356 if ( r0 >= radix ) break;
1357 }
1358
1359 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001360 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001361
1362 quotient = q1 * radix + q0;
1363
1364 return quotient;
1365#endif
1366}
1367
1368/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001369 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001370 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001371int 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 +00001372{
Paul Bakker23986e52011-04-24 08:57:21 +00001373 int ret;
1374 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001375 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001376
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001377 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1378 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001379
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001380 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1381 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001383 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001384 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001385 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1386 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001387 return( 0 );
1388 }
1389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1391 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001392 X.s = Y.s = 1;
1393
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001394 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1395 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1396 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1397 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001398
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001399 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001400 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001401 {
1402 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1404 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001405 }
1406 else k = 0;
1407
1408 n = X.n - 1;
1409 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001410 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001411
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001412 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001413 {
1414 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001415 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001416 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001417 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001418
1419 for( i = n; i > t ; i-- )
1420 {
1421 if( X.p[i] >= Y.p[t] )
1422 Z.p[i - t - 1] = ~0;
1423 else
1424 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001425 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1426 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001427 }
1428
1429 Z.p[i - t - 1]++;
1430 do
1431 {
1432 Z.p[i - t - 1]--;
1433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001434 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001435 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001436 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001437 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001438
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001439 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001440 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1441 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001442 T2.p[2] = X.p[i];
1443 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001444 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001446 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1447 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1448 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001449
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001450 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001451 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001452 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1453 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1454 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001455 Z.p[i - t - 1]--;
1456 }
1457 }
1458
1459 if( Q != NULL )
1460 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001461 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001462 Q->s = A->s * B->s;
1463 }
1464
1465 if( R != NULL )
1466 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001467 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001468 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001469 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001472 R->s = 1;
1473 }
1474
1475cleanup:
1476
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001477 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1478 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001479
1480 return( ret );
1481}
1482
1483/*
1484 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001485 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001486int 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 +00001487{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001488 mbedtls_mpi _B;
1489 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001490
1491 p[0] = ( b < 0 ) ? -b : b;
1492 _B.s = ( b < 0 ) ? -1 : 1;
1493 _B.n = 1;
1494 _B.p = p;
1495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001496 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001497}
1498
1499/*
1500 * Modulo: R = A mod B
1501 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001502int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001503{
1504 int ret;
1505
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1507 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001509 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1512 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001514 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1515 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001516
1517cleanup:
1518
1519 return( ret );
1520}
1521
1522/*
1523 * Modulo: r = A mod b
1524 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001525int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001526{
Paul Bakker23986e52011-04-24 08:57:21 +00001527 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001528 mbedtls_mpi_uint x, y, z;
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_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001532
1533 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001534 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001535
1536 /*
1537 * handle trivial cases
1538 */
1539 if( b == 1 )
1540 {
1541 *r = 0;
1542 return( 0 );
1543 }
1544
1545 if( b == 2 )
1546 {
1547 *r = A->p[0] & 1;
1548 return( 0 );
1549 }
1550
1551 /*
1552 * general case
1553 */
Paul Bakker23986e52011-04-24 08:57:21 +00001554 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001555 {
Paul Bakker23986e52011-04-24 08:57:21 +00001556 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001557 y = ( y << biH ) | ( x >> biH );
1558 z = y / b;
1559 y -= z * b;
1560
1561 x <<= biH;
1562 y = ( y << biH ) | ( x >> biH );
1563 z = y / b;
1564 y -= z * b;
1565 }
1566
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001567 /*
1568 * If A is negative, then the current y represents a negative value.
1569 * Flipping it to the positive side.
1570 */
1571 if( A->s < 0 && y != 0 )
1572 y = b - y;
1573
Paul Bakker5121ce52009-01-03 21:22:43 +00001574 *r = y;
1575
1576 return( 0 );
1577}
1578
1579/*
1580 * Fast Montgomery initialization (thanks to Tom St Denis)
1581 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001582static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001583{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001584 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001585 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001586
1587 x = m0;
1588 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001589
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001590 for( i = biL; i >= 8; i /= 2 )
1591 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001592
1593 *mm = ~x + 1;
1594}
1595
1596/*
1597 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1598 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001599static 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 +02001600 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001601{
Paul Bakker23986e52011-04-24 08:57:21 +00001602 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001603 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001604
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001605 if( T->n < N->n + 1 || T->p == NULL )
1606 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1607
Paul Bakker5121ce52009-01-03 21:22:43 +00001608 memset( T->p, 0, T->n * ciL );
1609
1610 d = T->p;
1611 n = N->n;
1612 m = ( B->n < n ) ? B->n : n;
1613
1614 for( i = 0; i < n; i++ )
1615 {
1616 /*
1617 * T = (T + u0*B + u1*N) / 2^biL
1618 */
1619 u0 = A->p[i];
1620 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1621
1622 mpi_mul_hlp( m, B->p, d, u0 );
1623 mpi_mul_hlp( n, N->p, d, u1 );
1624
1625 *d++ = u0; d[n + 1] = 0;
1626 }
1627
Paul Bakker66d5d072014-06-17 16:39:18 +02001628 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001629
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001630 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001631 mpi_sub_hlp( n, N->p, A->p );
1632 else
1633 /* prevent timing attacks */
1634 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001635
1636 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001637}
1638
1639/*
1640 * Montgomery reduction: A = A * R^-1 mod N
1641 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001642static 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 +00001643{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001644 mbedtls_mpi_uint z = 1;
1645 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001646
Paul Bakker8ddb6452013-02-27 14:56:33 +01001647 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001648 U.p = &z;
1649
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001650 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001651}
1652
1653/*
1654 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1655 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001656int 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 +00001657{
Paul Bakker23986e52011-04-24 08:57:21 +00001658 int ret;
1659 size_t wbits, wsize, one = 1;
1660 size_t i, j, nblimbs;
1661 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001662 mbedtls_mpi_uint ei, mm, state;
1663 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001664 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001665
Hanno Becker930ec7d2018-03-09 10:48:00 +00001666 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001667 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001669 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1670 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001671
1672 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001673 * Init temps and window size
1674 */
1675 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001676 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1677 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001678 memset( W, 0, sizeof( W ) );
1679
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001680 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001681
1682 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1683 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1684
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001685#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001686 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1687 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001688#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001689
Paul Bakker5121ce52009-01-03 21:22:43 +00001690 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001691 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1692 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1693 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001694
1695 /*
Paul Bakker50546922012-05-19 08:40:49 +00001696 * Compensate for negative A (and correct at the end)
1697 */
1698 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001699 if( neg )
1700 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001701 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001702 Apos.s = 1;
1703 A = &Apos;
1704 }
1705
1706 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001707 * If 1st call, pre-compute R^2 mod N
1708 */
1709 if( _RR == NULL || _RR->p == NULL )
1710 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001711 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1712 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1713 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001714
1715 if( _RR != NULL )
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 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001719 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001720
1721 /*
1722 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1723 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001724 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1725 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001726 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001727 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001728
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001729 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001730
1731 /*
1732 * X = R^2 * R^-1 mod N = R mod N
1733 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001734 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001735 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001736
1737 if( wsize > 1 )
1738 {
1739 /*
1740 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1741 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001742 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001743
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001744 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1745 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001746
1747 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001748 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001749
Paul Bakker5121ce52009-01-03 21:22:43 +00001750 /*
1751 * W[i] = W[i - 1] * W[1]
1752 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001753 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001754 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1756 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001757
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001758 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001759 }
1760 }
1761
1762 nblimbs = E->n;
1763 bufsize = 0;
1764 nbits = 0;
1765 wbits = 0;
1766 state = 0;
1767
1768 while( 1 )
1769 {
1770 if( bufsize == 0 )
1771 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001772 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001773 break;
1774
Paul Bakker0d7702c2013-10-29 16:18:35 +01001775 nblimbs--;
1776
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001777 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001778 }
1779
1780 bufsize--;
1781
1782 ei = (E->p[nblimbs] >> bufsize) & 1;
1783
1784 /*
1785 * skip leading 0s
1786 */
1787 if( ei == 0 && state == 0 )
1788 continue;
1789
1790 if( ei == 0 && state == 1 )
1791 {
1792 /*
1793 * out of window, square X
1794 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001795 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001796 continue;
1797 }
1798
1799 /*
1800 * add ei to current window
1801 */
1802 state = 2;
1803
1804 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001805 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001806
1807 if( nbits == wsize )
1808 {
1809 /*
1810 * X = X^wsize R^-1 mod N
1811 */
1812 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001813 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001814
1815 /*
1816 * X = X * W[wbits] R^-1 mod N
1817 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001818 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001819
1820 state--;
1821 nbits = 0;
1822 wbits = 0;
1823 }
1824 }
1825
1826 /*
1827 * process the remaining bits
1828 */
1829 for( i = 0; i < nbits; i++ )
1830 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001831 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001832
1833 wbits <<= 1;
1834
Paul Bakker66d5d072014-06-17 16:39:18 +02001835 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001836 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001837 }
1838
1839 /*
1840 * X = A^E * R * R^-1 mod N = A^E mod N
1841 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001842 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001843
Hanno Beckera4af1c42017-04-18 09:07:45 +01001844 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001845 {
1846 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001847 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001848 }
1849
Paul Bakker5121ce52009-01-03 21:22:43 +00001850cleanup:
1851
Paul Bakker66d5d072014-06-17 16:39:18 +02001852 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001853 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001854
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001855 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001856
Paul Bakker75a28602014-03-31 12:08:17 +02001857 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001858 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001859
1860 return( ret );
1861}
1862
Paul Bakker5121ce52009-01-03 21:22:43 +00001863/*
1864 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1865 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001866int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001867{
Paul Bakker23986e52011-04-24 08:57:21 +00001868 int ret;
1869 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001870 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001871
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001872 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001873
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001874 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1875 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001876
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001877 lz = mbedtls_mpi_lsb( &TA );
1878 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001879
Paul Bakker66d5d072014-06-17 16:39:18 +02001880 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001881 lz = lzt;
1882
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001883 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1884 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001885
Paul Bakker5121ce52009-01-03 21:22:43 +00001886 TA.s = TB.s = 1;
1887
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001888 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001889 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001890 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1891 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001892
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001893 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001894 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001895 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1896 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001897 }
1898 else
1899 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001900 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1901 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001902 }
1903 }
1904
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001905 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1906 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001907
1908cleanup:
1909
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001910 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001911
1912 return( ret );
1913}
1914
Paul Bakker33dc46b2014-04-30 16:11:39 +02001915/*
1916 * Fill X with size bytes of random.
1917 *
1918 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001919 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001920 * deterministic, eg for tests).
1921 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001922int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001923 int (*f_rng)(void *, unsigned char *, size_t),
1924 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001925{
Paul Bakker23986e52011-04-24 08:57:21 +00001926 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001927 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001928
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 if( size > MBEDTLS_MPI_MAX_SIZE )
1930 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001931
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001932 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1933 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001934
1935cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01001936 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001937 return( ret );
1938}
1939
Paul Bakker5121ce52009-01-03 21:22:43 +00001940/*
1941 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1942 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001943int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001944{
1945 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001946 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001947
Hanno Becker4bcb4912017-04-18 15:49:39 +01001948 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001949 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001950
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001951 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1952 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1953 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001954
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001955 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001957 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001958 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001960 goto cleanup;
1961 }
1962
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1964 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1965 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1966 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001967
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001968 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1969 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1970 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1971 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001972
1973 do
1974 {
1975 while( ( TU.p[0] & 1 ) == 0 )
1976 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001977 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001978
1979 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1980 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001981 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1982 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001983 }
1984
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001985 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1986 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001987 }
1988
1989 while( ( TV.p[0] & 1 ) == 0 )
1990 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001991 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001992
1993 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1994 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001995 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1996 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001997 }
1998
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001999 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2000 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002001 }
2002
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002003 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002004 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002005 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2006 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2007 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002008 }
2009 else
2010 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002011 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2012 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2013 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002014 }
2015 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002017
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002018 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2019 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002020
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002021 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2022 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002023
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002024 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002025
2026cleanup:
2027
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002028 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2029 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2030 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002031
2032 return( ret );
2033}
2034
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002035#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002036
Paul Bakker5121ce52009-01-03 21:22:43 +00002037static const int small_prime[] =
2038{
2039 3, 5, 7, 11, 13, 17, 19, 23,
2040 29, 31, 37, 41, 43, 47, 53, 59,
2041 61, 67, 71, 73, 79, 83, 89, 97,
2042 101, 103, 107, 109, 113, 127, 131, 137,
2043 139, 149, 151, 157, 163, 167, 173, 179,
2044 181, 191, 193, 197, 199, 211, 223, 227,
2045 229, 233, 239, 241, 251, 257, 263, 269,
2046 271, 277, 281, 283, 293, 307, 311, 313,
2047 317, 331, 337, 347, 349, 353, 359, 367,
2048 373, 379, 383, 389, 397, 401, 409, 419,
2049 421, 431, 433, 439, 443, 449, 457, 461,
2050 463, 467, 479, 487, 491, 499, 503, 509,
2051 521, 523, 541, 547, 557, 563, 569, 571,
2052 577, 587, 593, 599, 601, 607, 613, 617,
2053 619, 631, 641, 643, 647, 653, 659, 661,
2054 673, 677, 683, 691, 701, 709, 719, 727,
2055 733, 739, 743, 751, 757, 761, 769, 773,
2056 787, 797, 809, 811, 821, 823, 827, 829,
2057 839, 853, 857, 859, 863, 877, 881, 883,
2058 887, 907, 911, 919, 929, 937, 941, 947,
2059 953, 967, 971, 977, 983, 991, 997, -103
2060};
2061
2062/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002063 * Small divisors test (X must be positive)
2064 *
2065 * Return values:
2066 * 0: no small factor (possible prime, more tests needed)
2067 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002068 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002069 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002070 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002071static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002072{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002073 int ret = 0;
2074 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002075 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002076
Paul Bakker5121ce52009-01-03 21:22:43 +00002077 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002078 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002079
2080 for( i = 0; small_prime[i] > 0; i++ )
2081 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002082 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002083 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002084
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002085 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002086
2087 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002088 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002089 }
2090
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002091cleanup:
2092 return( ret );
2093}
2094
2095/*
2096 * Miller-Rabin pseudo-primality test (HAC 4.24)
2097 */
Janos Follath72d555d2018-09-03 14:45:23 +01002098static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002099 int (*f_rng)(void *, unsigned char *, size_t),
2100 void *p_rng )
2101{
Pascal Junodb99183d2015-03-11 16:49:45 +01002102 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002103 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002104 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002105
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002106 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2107 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002108
Paul Bakker5121ce52009-01-03 21:22:43 +00002109 /*
2110 * W = |X| - 1
2111 * R = W >> lsb( W )
2112 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002113 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2114 s = mbedtls_mpi_lsb( &W );
2115 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2116 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002117
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002118 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002119
Janos Follath72d555d2018-09-03 14:45:23 +01002120 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002121 {
2122 /*
2123 * pick a random A, 1 < A < |X| - 1
2124 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002125 count = 0;
2126 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002127 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002128
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002129 j = mbedtls_mpi_bitlen( &A );
2130 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002131 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002132 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002133 }
2134
2135 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002136 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002137 }
2138
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002139 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2140 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002141
2142 /*
2143 * A = A^R mod |X|
2144 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002146
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002147 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2148 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002149 continue;
2150
2151 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002152 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002153 {
2154 /*
2155 * A = A * A mod |X|
2156 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002157 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2158 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002161 break;
2162
2163 j++;
2164 }
2165
2166 /*
2167 * not prime if A != |X| - 1 or A == 1
2168 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002169 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2170 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002171 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002172 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002173 break;
2174 }
2175 }
2176
2177cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002178 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2179 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002180
2181 return( ret );
2182}
2183
2184/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002185 * Pseudo-primality test: small factors, then Miller-Rabin
2186 */
Darryl Green94759f62018-10-16 15:09:19 +01002187static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002188 int (*f_rng)(void *, unsigned char *, size_t),
2189 void *p_rng )
2190{
2191 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002192 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002193
2194 XX.s = 1;
2195 XX.n = X->n;
2196 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002197
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2199 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2200 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002202 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002203 return( 0 );
2204
2205 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2206 {
2207 if( ret == 1 )
2208 return( 0 );
2209
2210 return( ret );
2211 }
2212
Janos Follath72d555d2018-09-03 14:45:23 +01002213 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2214}
2215
2216/*
2217 * Pseudo-primality test, error probability 2^-80
2218 */
2219int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2220 int (*f_rng)(void *, unsigned char *, size_t),
2221 void *p_rng )
2222{
2223 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002224}
2225
2226/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002227 * Prime number generation
2228 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002229int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002230 int (*f_rng)(void *, unsigned char *, size_t),
2231 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002232{
Paul Bakker23986e52011-04-24 08:57:21 +00002233 int ret;
2234 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002235 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002236 mbedtls_mpi_uint r;
2237 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002239 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2240 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002241
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002242 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002243
2244 n = BITS_TO_LIMBS( nbits );
2245
Janos Follath72d555d2018-09-03 14:45:23 +01002246 /*
2247 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2248 */
2249 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2250 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2251 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2252
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002253 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002254
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002255 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002256 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002257
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002258 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002259
2260 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002261
2262 if( dh_flag == 0 )
2263 {
Janos Follath72d555d2018-09-03 14:45:23 +01002264 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002265 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002266 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002267 goto cleanup;
2268
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002269 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002270 }
2271 }
2272 else
2273 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002274 /*
2275 * An necessary condition for Y and X = 2Y + 1 to be prime
2276 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2277 * Make sure it is satisfied, while keeping X = 3 mod 4
2278 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002279
2280 X->p[0] |= 2;
2281
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002282 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002283 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002284 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002285 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002286 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002287
2288 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002289 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2290 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002291
2292 while( 1 )
2293 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002294 /*
2295 * First, check small factors for X and Y
2296 * before doing Miller-Rabin on any of them
2297 */
2298 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2299 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002300 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2301 == 0 &&
2302 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2303 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002304 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002305 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002306 }
2307
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002308 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002309 goto cleanup;
2310
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002311 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002312 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002313 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2314 * so up Y by 6 and X by 12.
2315 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002316 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2317 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002318 }
2319 }
2320
2321cleanup:
2322
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002323 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002324
2325 return( ret );
2326}
2327
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002328#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002329
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002331
Paul Bakker23986e52011-04-24 08:57:21 +00002332#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002333
2334static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2335{
2336 { 693, 609, 21 },
2337 { 1764, 868, 28 },
2338 { 768454923, 542167814, 1 }
2339};
2340
Paul Bakker5121ce52009-01-03 21:22:43 +00002341/*
2342 * Checkup routine
2343 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002344int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002345{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002346 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002349 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2350 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002351
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002352 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002353 "EFE021C2645FD1DC586E69184AF4A31E" \
2354 "D5F53E93B5F123FA41680867BA110131" \
2355 "944FE7952E2517337780CB0DB80E61AA" \
2356 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002358 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002359 "B2E7EFD37075B9F03FF989C7C5051C20" \
2360 "34D2A323810251127E7BF8625A4F49A5" \
2361 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2362 "5B5C25763222FEFCCFC38B832366C29E" ) );
2363
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002364 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002365 "0066A198186C18C10B2F5ED9B522752A" \
2366 "9830B69916E535C8F047518A889A43A5" \
2367 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002369 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002370
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002371 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002372 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2373 "9E857EA95A03512E2BAE7391688D264A" \
2374 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2375 "8001B72E848A38CAE1C65F78E56ABDEF" \
2376 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2377 "ECF677152EF804370C1A305CAF3B5BF1" \
2378 "30879B56C61DE584A0F53A2447A51E" ) );
2379
2380 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002381 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002384 {
2385 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002386 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002387
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002388 ret = 1;
2389 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002390 }
2391
2392 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002393 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002394
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002395 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002397 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002398 "256567336059E52CAE22925474705F39A94" ) );
2399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002400 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002401 "6613F26162223DF488E9CD48CC132C7A" \
2402 "0AC93C701B001B092E4E5B9F73BCD27B" \
2403 "9EE50D0657C77F374E903CDFA4C642" ) );
2404
2405 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002406 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002408 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2409 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002410 {
2411 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002412 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002413
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002414 ret = 1;
2415 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002416 }
2417
2418 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002419 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002420
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002421 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002422
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002423 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002424 "36E139AEA55215609D2816998ED020BB" \
2425 "BD96C37890F65171D948E9BC7CBAA4D9" \
2426 "325D24D6A3C12710F10A09FA08AB87" ) );
2427
2428 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002429 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002431 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002432 {
2433 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002435
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002436 ret = 1;
2437 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002438 }
2439
2440 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002441 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002443 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002445 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002446 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2447 "C3DBA76456363A10869622EAC2DD84EC" \
2448 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2449
2450 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002451 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002453 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002454 {
2455 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002456 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002457
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002458 ret = 1;
2459 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002460 }
2461
2462 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002463 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002464
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002465 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002466 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002467
Paul Bakker66d5d072014-06-17 16:39:18 +02002468 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002469 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002470 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2471 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002474
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002476 {
2477 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002478 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002479
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002480 ret = 1;
2481 goto cleanup;
2482 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002483 }
2484
2485 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002486 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002487
Paul Bakker5121ce52009-01-03 21:22:43 +00002488cleanup:
2489
2490 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002491 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002493 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2494 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002495
2496 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002497 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002498
2499 return( ret );
2500}
2501
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002502#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002504#endif /* MBEDTLS_BIGNUM_C */