blob: ba817bebf5aa2747b6ef508eac06db780c0aaeab [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000048
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <string.h>
50
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000052#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020053#else
Rich Evans00ab4702015-02-06 13:43:58 +000054#include <stdio.h>
55#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020057#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020059#endif
60
Paul Bakker34617722014-06-13 17:20:13 +020061/* Implementation that should never be optimized out by the compiler */
Alexey Skalozube17a8da2016-01-13 17:19:33 +020062static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) {
Alexey Skalozub3d53f412016-01-13 16:53:40 +020063 volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0;
Paul Bakker34617722014-06-13 17:20:13 +020064}
65
Hanno Becker88807112017-10-18 12:41:30 +010066/* Implementation that should never be optimized out by the compiler */
67static void mbedtls_zeroize( void *v, size_t n ) {
68 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
69}
70
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000072#define biL (ciL << 3) /* bits in limb */
73#define biH (ciL << 2) /* half limb size */
74
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010075#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
76
Paul Bakker5121ce52009-01-03 21:22:43 +000077/*
78 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020079 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000080 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020081#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
82#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000083
84/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000085 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000086 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020087void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000088{
Paul Bakker6c591fa2011-05-05 11:49:20 +000089 if( X == NULL )
90 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000091
Paul Bakker6c591fa2011-05-05 11:49:20 +000092 X->s = 1;
93 X->n = 0;
94 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000095}
96
97/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000098 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000099 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000101{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000102 if( X == NULL )
103 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000104
Paul Bakker6c591fa2011-05-05 11:49:20 +0000105 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000106 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200107 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200108 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000109 }
110
Paul Bakker6c591fa2011-05-05 11:49:20 +0000111 X->s = 1;
112 X->n = 0;
113 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000114}
115
116/*
117 * Enlarge to the specified number of limbs
118 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000120{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200123 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200124 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000125
Paul Bakker5121ce52009-01-03 21:22:43 +0000126 if( X->n < nblimbs )
127 {
Simon Butcher29176892016-05-20 00:19:09 +0100128 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200129 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000130
Paul Bakker5121ce52009-01-03 21:22:43 +0000131 if( X->p != NULL )
132 {
133 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200134 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000136 }
137
138 X->n = nblimbs;
139 X->p = p;
140 }
141
142 return( 0 );
143}
144
145/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100146 * Resize down as much as possible,
147 * while keeping at least the specified number of limbs
148 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100150{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152 size_t i;
153
154 /* Actually resize up in this case */
155 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100157
158 for( i = X->n - 1; i > 0; i-- )
159 if( X->p[i] != 0 )
160 break;
161 i++;
162
163 if( i < nblimbs )
164 i = nblimbs;
165
Simon Butcher29176892016-05-20 00:19:09 +0100166 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200167 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100168
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100169 if( X->p != NULL )
170 {
171 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200172 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100174 }
175
176 X->n = i;
177 X->p = p;
178
179 return( 0 );
180}
181
182/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000183 * Copy the contents of Y into X
184 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000186{
Paul Bakker23986e52011-04-24 08:57:21 +0000187 int ret;
188 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000189
190 if( X == Y )
191 return( 0 );
192
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200193 if( Y->p == NULL )
194 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200195 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200196 return( 0 );
197 }
198
Paul Bakker5121ce52009-01-03 21:22:43 +0000199 for( i = Y->n - 1; i > 0; i-- )
200 if( Y->p[i] != 0 )
201 break;
202 i++;
203
204 X->s = Y->s;
205
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000207
208 memset( X->p, 0, X->n * ciL );
209 memcpy( X->p, Y->p, i * ciL );
210
211cleanup:
212
213 return( ret );
214}
215
216/*
217 * Swap the contents of X and Y
218 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000220{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200223 memcpy( &T, X, sizeof( mbedtls_mpi ) );
224 memcpy( X, Y, sizeof( mbedtls_mpi ) );
225 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000226}
227
228/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100229 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100230 * about whether the assignment was made or not.
231 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100234{
235 int ret = 0;
236 size_t i;
237
Pascal Junodb99183d2015-03-11 16:49:45 +0100238 /* make sure assign is 0 or 1 in a time-constant manner */
239 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100242
Paul Bakker66d5d072014-06-17 16:39:18 +0200243 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100244
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100245 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200246 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100247
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100248 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200249 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250
251cleanup:
252 return( ret );
253}
254
255/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100256 * Conditionally swap X and Y, without leaking information
257 * about whether the swap was made or not.
258 * Here it is not ok to simply swap the pointers, which whould lead to
259 * different memory access patterns when X and Y are used afterwards.
260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100262{
263 int ret, s;
264 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100266
267 if( X == Y )
268 return( 0 );
269
Pascal Junodb99183d2015-03-11 16:49:45 +0100270 /* make sure swap is 0 or 1 in a time-constant manner */
271 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100272
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200273 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
274 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100275
276 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200277 X->s = X->s * ( 1 - swap ) + Y->s * swap;
278 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100279
280
281 for( i = 0; i < X->n; i++ )
282 {
283 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200284 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
285 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286 }
287
288cleanup:
289 return( ret );
290}
291
292/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000293 * Set value from integer
294 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200295int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000296{
297 int ret;
298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000300 memset( X->p, 0, X->n * ciL );
301
302 X->p[0] = ( z < 0 ) ? -z : z;
303 X->s = ( z < 0 ) ? -1 : 1;
304
305cleanup:
306
307 return( ret );
308}
309
310/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000311 * Get a specific bit
312 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200313int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000314{
315 if( X->n * biL <= pos )
316 return( 0 );
317
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200318 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000319}
320
Gilles Peskine220cc172018-11-20 16:47:47 +0100321/* Get a specific byte, without range checks. */
322#define GET_BYTE( X, i ) \
323 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
324
Paul Bakker2f5947e2011-05-18 15:47:11 +0000325/*
326 * Set a bit to a specific value of 0 or 1
327 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200328int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000329{
330 int ret = 0;
331 size_t off = pos / biL;
332 size_t idx = pos % biL;
333
334 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200335 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200336
Paul Bakker2f5947e2011-05-18 15:47:11 +0000337 if( X->n * biL <= pos )
338 {
339 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200340 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200342 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000343 }
344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200345 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
346 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000347
348cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200349
Paul Bakker2f5947e2011-05-18 15:47:11 +0000350 return( ret );
351}
352
353/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200354 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000355 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000357{
Paul Bakker23986e52011-04-24 08:57:21 +0000358 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000359
360 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000361 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000362 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
363 return( count );
364
365 return( 0 );
366}
367
368/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000369 * Count leading zero bits in a given integer
370 */
371static size_t mbedtls_clz( const mbedtls_mpi_uint x )
372{
373 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100374 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000375
376 for( j = 0; j < biL; j++ )
377 {
378 if( x & mask ) break;
379
380 mask >>= 1;
381 }
382
383 return j;
384}
385
386/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200387 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000388 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200389size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000390{
Paul Bakker23986e52011-04-24 08:57:21 +0000391 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000392
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200393 if( X->n == 0 )
394 return( 0 );
395
Paul Bakker5121ce52009-01-03 21:22:43 +0000396 for( i = X->n - 1; i > 0; i-- )
397 if( X->p[i] != 0 )
398 break;
399
Simon Butcher15b15d12015-11-26 19:35:03 +0000400 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000401
Paul Bakker23986e52011-04-24 08:57:21 +0000402 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000403}
404
405/*
406 * Return the total size in bytes
407 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000409{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200410 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000411}
412
413/*
414 * Convert an ASCII character to digit value
415 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000417{
418 *d = 255;
419
420 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
421 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
422 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424 if( *d >= (mbedtls_mpi_uint) radix )
425 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
427 return( 0 );
428}
429
430/*
431 * Import from an ASCII string
432 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000434{
Paul Bakker23986e52011-04-24 08:57:21 +0000435 int ret;
436 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437 mbedtls_mpi_uint d;
438 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000439
440 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200443 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000444
Paul Bakkerff60ee62010-03-16 21:09:09 +0000445 slen = strlen( s );
446
Paul Bakker5121ce52009-01-03 21:22:43 +0000447 if( radix == 16 )
448 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100449 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200450 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
451
Paul Bakkerff60ee62010-03-16 21:09:09 +0000452 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000453
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
455 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000456
Paul Bakker23986e52011-04-24 08:57:21 +0000457 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 {
Paul Bakker23986e52011-04-24 08:57:21 +0000459 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000460 {
461 X->s = -1;
462 break;
463 }
464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200466 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000467 }
468 }
469 else
470 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000472
Paul Bakkerff60ee62010-03-16 21:09:09 +0000473 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 {
475 if( i == 0 && s[i] == '-' )
476 {
477 X->s = -1;
478 continue;
479 }
480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
482 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000483
484 if( X->s == 1 )
485 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000487 }
488 else
489 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000491 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000492 }
493 }
494
495cleanup:
496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000498
499 return( ret );
500}
501
502/*
Ron Eldore6cbfc32018-11-20 14:07:01 +0200503 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000504 */
Ron Eldore6cbfc32018-11-20 14:07:01 +0200505static int mpi_write_hlp( mbedtls_mpi *X, int radix,
506 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000507{
508 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 mbedtls_mpi_uint r;
Ron Eldore6cbfc32018-11-20 14:07:01 +0200510 size_t length = 0;
511 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000512
Ron Eldore6cbfc32018-11-20 14:07:01 +0200513 do
514 {
515 if( length >= buflen )
516 {
517 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
518 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000519
Ron Eldore6cbfc32018-11-20 14:07:01 +0200520 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
521 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
522 /*
523 * Write the residue in the current position, as an ASCII character.
524 */
525 if( r < 0xA )
526 *(--p_end) = (char)( '0' + r );
527 else
528 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000529
Ron Eldore6cbfc32018-11-20 14:07:01 +0200530 length++;
531 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000532
Ron Eldore6cbfc32018-11-20 14:07:01 +0200533 memmove( *p, p_end, length );
534 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000535
536cleanup:
537
538 return( ret );
539}
540
541/*
542 * Export into an ASCII string
543 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100544int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
545 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000546{
Paul Bakker23986e52011-04-24 08:57:21 +0000547 int ret = 0;
548 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000549 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000551
552 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000554
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200555 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000556 if( radix >= 4 ) n >>= 1;
557 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000558 /*
559 * Round up the buffer length to an even value to ensure that there is
560 * enough room for hexadecimal values that can be represented in an odd
561 * number of digits.
562 */
563 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000564
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100565 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000566 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100567 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200568 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000569 }
570
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100571 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200572 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000573
574 if( X->s == -1 )
575 *p++ = '-';
576
577 if( radix == 16 )
578 {
Paul Bakker23986e52011-04-24 08:57:21 +0000579 int c;
580 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000581
Paul Bakker23986e52011-04-24 08:57:21 +0000582 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000583 {
Paul Bakker23986e52011-04-24 08:57:21 +0000584 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000585 {
Paul Bakker23986e52011-04-24 08:57:21 +0000586 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000587
Paul Bakker6c343d72014-07-10 14:36:19 +0200588 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000589 continue;
590
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000591 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000592 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000593 k = 1;
594 }
595 }
596 }
597 else
598 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000600
601 if( T.s == -1 )
602 T.s = 1;
603
Ron Eldore6cbfc32018-11-20 14:07:01 +0200604 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000605 }
606
607 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100608 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000609
610cleanup:
611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000613
614 return( ret );
615}
616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000618/*
619 * Read X from an opened file
620 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000622{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200623 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000624 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000625 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000626 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000627 * Buffer should have space for (short) label and decimal formatted MPI,
628 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000629 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000631
632 memset( s, 0, sizeof( s ) );
633 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200634 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000635
636 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000637 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000639
Hanno Beckerb2034b72017-04-26 11:46:46 +0100640 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
641 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000642
643 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100644 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000645 if( mpi_get_digit( &d, radix, *p ) != 0 )
646 break;
647
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000649}
650
651/*
652 * Write X into an opened file (or stdout if fout == NULL)
653 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200654int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000655{
Paul Bakker23986e52011-04-24 08:57:21 +0000656 int ret;
657 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000658 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000659 * Buffer should have space for (short) label and decimal formatted MPI,
660 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000661 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000663
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100664 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000665
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100666 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000667
668 if( p == NULL ) p = "";
669
670 plen = strlen( p );
671 slen = strlen( s );
672 s[slen++] = '\r';
673 s[slen++] = '\n';
674
675 if( fout != NULL )
676 {
677 if( fwrite( p, 1, plen, fout ) != plen ||
678 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200679 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000680 }
681 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000683
684cleanup:
685
686 return( ret );
687}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200688#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000689
690/*
691 * Import X from unsigned binary data, big endian
692 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200693int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000694{
Paul Bakker23986e52011-04-24 08:57:21 +0000695 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100696 size_t i, j;
697 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
Hanno Becker073c1992017-10-17 15:17:27 +0100699 /* Ensure that target MPI has exactly the necessary number of limbs */
700 if( X->n != limbs )
701 {
702 mbedtls_mpi_free( X );
703 mbedtls_mpi_init( X );
704 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
705 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000706
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000708
Hanno Becker073c1992017-10-17 15:17:27 +0100709 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
712cleanup:
713
714 return( ret );
715}
716
717/*
718 * Export X into unsigned binary data, big endian
719 */
Gilles Peskine220cc172018-11-20 16:47:47 +0100720int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
721 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000722{
Gilles Peskine220cc172018-11-20 16:47:47 +0100723 size_t stored_bytes = X->n * ciL;
724 size_t bytes_to_copy;
725 unsigned char *p;
726 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000727
Gilles Peskine220cc172018-11-20 16:47:47 +0100728 if( stored_bytes < buflen )
729 {
730 /* There is enough space in the output buffer. Write initial
731 * null bytes and record the position at which to start
732 * writing the significant bytes. In this case, the execution
733 * trace of this function does not depend on the value of the
734 * number. */
735 bytes_to_copy = stored_bytes;
736 p = buf + buflen - stored_bytes;
737 memset( buf, 0, buflen - stored_bytes );
738 }
739 else
740 {
741 /* The output buffer is smaller than the allocated size of X.
742 * However X may fit if its leading bytes are zero. */
743 bytes_to_copy = buflen;
744 p = buf;
745 for( i = bytes_to_copy; i < stored_bytes; i++ )
746 {
747 if( GET_BYTE( X, i ) != 0 )
748 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
749 }
750 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000751
Gilles Peskine220cc172018-11-20 16:47:47 +0100752 for( i = 0; i < bytes_to_copy; i++ )
753 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000754
755 return( 0 );
756}
757
758/*
759 * Left-shift: X <<= count
760 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200761int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000762{
Paul Bakker23986e52011-04-24 08:57:21 +0000763 int ret;
764 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200765 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000766
767 v0 = count / (biL );
768 t1 = count & (biL - 1);
769
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200770 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000771
Paul Bakkerf9688572011-05-05 10:00:45 +0000772 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200773 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000774
775 ret = 0;
776
777 /*
778 * shift by count / limb_size
779 */
780 if( v0 > 0 )
781 {
Paul Bakker23986e52011-04-24 08:57:21 +0000782 for( i = X->n; i > v0; i-- )
783 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000784
Paul Bakker23986e52011-04-24 08:57:21 +0000785 for( ; i > 0; i-- )
786 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000787 }
788
789 /*
790 * shift by count % limb_size
791 */
792 if( t1 > 0 )
793 {
794 for( i = v0; i < X->n; i++ )
795 {
796 r1 = X->p[i] >> (biL - t1);
797 X->p[i] <<= t1;
798 X->p[i] |= r0;
799 r0 = r1;
800 }
801 }
802
803cleanup:
804
805 return( ret );
806}
807
808/*
809 * Right-shift: X >>= count
810 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200811int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000812{
Paul Bakker23986e52011-04-24 08:57:21 +0000813 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200814 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000815
816 v0 = count / biL;
817 v1 = count & (biL - 1);
818
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100819 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200820 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100821
Paul Bakker5121ce52009-01-03 21:22:43 +0000822 /*
823 * shift by count / limb_size
824 */
825 if( v0 > 0 )
826 {
827 for( i = 0; i < X->n - v0; i++ )
828 X->p[i] = X->p[i + v0];
829
830 for( ; i < X->n; i++ )
831 X->p[i] = 0;
832 }
833
834 /*
835 * shift by count % limb_size
836 */
837 if( v1 > 0 )
838 {
Paul Bakker23986e52011-04-24 08:57:21 +0000839 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000840 {
Paul Bakker23986e52011-04-24 08:57:21 +0000841 r1 = X->p[i - 1] << (biL - v1);
842 X->p[i - 1] >>= v1;
843 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000844 r0 = r1;
845 }
846 }
847
848 return( 0 );
849}
850
851/*
852 * Compare unsigned values
853 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200854int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000855{
Paul Bakker23986e52011-04-24 08:57:21 +0000856 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000857
Paul Bakker23986e52011-04-24 08:57:21 +0000858 for( i = X->n; i > 0; i-- )
859 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000860 break;
861
Paul Bakker23986e52011-04-24 08:57:21 +0000862 for( j = Y->n; j > 0; j-- )
863 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000864 break;
865
Paul Bakker23986e52011-04-24 08:57:21 +0000866 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000867 return( 0 );
868
869 if( i > j ) return( 1 );
870 if( j > i ) return( -1 );
871
Paul Bakker23986e52011-04-24 08:57:21 +0000872 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000873 {
Paul Bakker23986e52011-04-24 08:57:21 +0000874 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
875 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000876 }
877
878 return( 0 );
879}
880
881/*
882 * Compare signed values
883 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200884int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000885{
Paul Bakker23986e52011-04-24 08:57:21 +0000886 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000887
Paul Bakker23986e52011-04-24 08:57:21 +0000888 for( i = X->n; i > 0; i-- )
889 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000890 break;
891
Paul Bakker23986e52011-04-24 08:57:21 +0000892 for( j = Y->n; j > 0; j-- )
893 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000894 break;
895
Paul Bakker23986e52011-04-24 08:57:21 +0000896 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000897 return( 0 );
898
899 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000900 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000901
902 if( X->s > 0 && Y->s < 0 ) return( 1 );
903 if( Y->s > 0 && X->s < 0 ) return( -1 );
904
Paul Bakker23986e52011-04-24 08:57:21 +0000905 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000906 {
Paul Bakker23986e52011-04-24 08:57:21 +0000907 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
908 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000909 }
910
911 return( 0 );
912}
913
914/*
915 * Compare signed values
916 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200917int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000918{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919 mbedtls_mpi Y;
920 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000921
922 *p = ( z < 0 ) ? -z : z;
923 Y.s = ( z < 0 ) ? -1 : 1;
924 Y.n = 1;
925 Y.p = p;
926
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200927 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000928}
929
930/*
931 * Unsigned addition: X = |A| + |B| (HAC 14.7)
932 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200933int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000934{
Paul Bakker23986e52011-04-24 08:57:21 +0000935 int ret;
936 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100937 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000938
939 if( X == B )
940 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000942 }
943
944 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200945 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200946
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000947 /*
948 * X should always be positive as a result of unsigned additions.
949 */
950 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000951
Paul Bakker23986e52011-04-24 08:57:21 +0000952 for( j = B->n; j > 0; j-- )
953 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000954 break;
955
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200956 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000957
958 o = B->p; p = X->p; c = 0;
959
Janos Follath6c922682015-10-30 17:43:11 +0100960 /*
961 * tmp is used because it might happen that p == o
962 */
Paul Bakker23986e52011-04-24 08:57:21 +0000963 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000964 {
Janos Follath6c922682015-10-30 17:43:11 +0100965 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000966 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100967 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000968 }
969
970 while( c != 0 )
971 {
972 if( i >= X->n )
973 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200974 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000975 p = X->p + i;
976 }
977
Paul Bakker2d319fd2012-09-16 21:34:26 +0000978 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000979 }
980
981cleanup:
982
983 return( ret );
984}
985
986/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200987 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000988 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200989static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000990{
Paul Bakker23986e52011-04-24 08:57:21 +0000991 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200992 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000993
994 for( i = c = 0; i < n; i++, s++, d++ )
995 {
996 z = ( *d < c ); *d -= c;
997 c = ( *d < *s ) + z; *d -= *s;
998 }
999
1000 while( c != 0 )
1001 {
1002 z = ( *d < c ); *d -= c;
1003 c = z; i++; d++;
1004 }
1005}
1006
1007/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001008 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001009 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001010int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001011{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001012 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001013 int ret;
1014 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001015
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1017 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001018
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001020
1021 if( X == B )
1022 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001023 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001024 B = &TB;
1025 }
1026
1027 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001028 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001029
Paul Bakker1ef7a532009-06-20 10:50:55 +00001030 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001031 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001032 */
1033 X->s = 1;
1034
Paul Bakker5121ce52009-01-03 21:22:43 +00001035 ret = 0;
1036
Paul Bakker23986e52011-04-24 08:57:21 +00001037 for( n = B->n; n > 0; n-- )
1038 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001039 break;
1040
Paul Bakker23986e52011-04-24 08:57:21 +00001041 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001042
1043cleanup:
1044
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001045 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001046
1047 return( ret );
1048}
1049
1050/*
1051 * Signed addition: X = A + B
1052 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001053int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001054{
1055 int ret, s = A->s;
1056
1057 if( A->s * B->s < 0 )
1058 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001059 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001060 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001061 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001062 X->s = s;
1063 }
1064 else
1065 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001066 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001067 X->s = -s;
1068 }
1069 }
1070 else
1071 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001072 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001073 X->s = s;
1074 }
1075
1076cleanup:
1077
1078 return( ret );
1079}
1080
1081/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001082 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001083 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001084int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001085{
1086 int ret, s = A->s;
1087
1088 if( A->s * B->s > 0 )
1089 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001090 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001091 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001092 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001093 X->s = s;
1094 }
1095 else
1096 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001097 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001098 X->s = -s;
1099 }
1100 }
1101 else
1102 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001103 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001104 X->s = s;
1105 }
1106
1107cleanup:
1108
1109 return( ret );
1110}
1111
1112/*
1113 * Signed addition: X = A + b
1114 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001116{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001117 mbedtls_mpi _B;
1118 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001119
1120 p[0] = ( b < 0 ) ? -b : b;
1121 _B.s = ( b < 0 ) ? -1 : 1;
1122 _B.n = 1;
1123 _B.p = p;
1124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001125 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001126}
1127
1128/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001129 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001130 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001131int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001132{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001133 mbedtls_mpi _B;
1134 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001135
1136 p[0] = ( b < 0 ) ? -b : b;
1137 _B.s = ( b < 0 ) ? -1 : 1;
1138 _B.n = 1;
1139 _B.p = p;
1140
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001141 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001142}
1143
1144/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001145 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001146 */
1147static
1148#if defined(__APPLE__) && defined(__arm__)
1149/*
1150 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1151 * appears to need this to prevent bad ARM code generation at -O3.
1152 */
1153__attribute__ ((noinline))
1154#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001155void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001156{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001157 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001158
1159#if defined(MULADDC_HUIT)
1160 for( ; i >= 8; i -= 8 )
1161 {
1162 MULADDC_INIT
1163 MULADDC_HUIT
1164 MULADDC_STOP
1165 }
1166
1167 for( ; i > 0; i-- )
1168 {
1169 MULADDC_INIT
1170 MULADDC_CORE
1171 MULADDC_STOP
1172 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001173#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001174 for( ; i >= 16; i -= 16 )
1175 {
1176 MULADDC_INIT
1177 MULADDC_CORE MULADDC_CORE
1178 MULADDC_CORE MULADDC_CORE
1179 MULADDC_CORE MULADDC_CORE
1180 MULADDC_CORE MULADDC_CORE
1181
1182 MULADDC_CORE MULADDC_CORE
1183 MULADDC_CORE MULADDC_CORE
1184 MULADDC_CORE MULADDC_CORE
1185 MULADDC_CORE MULADDC_CORE
1186 MULADDC_STOP
1187 }
1188
1189 for( ; i >= 8; i -= 8 )
1190 {
1191 MULADDC_INIT
1192 MULADDC_CORE MULADDC_CORE
1193 MULADDC_CORE MULADDC_CORE
1194
1195 MULADDC_CORE MULADDC_CORE
1196 MULADDC_CORE MULADDC_CORE
1197 MULADDC_STOP
1198 }
1199
1200 for( ; i > 0; i-- )
1201 {
1202 MULADDC_INIT
1203 MULADDC_CORE
1204 MULADDC_STOP
1205 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001206#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001207
1208 t++;
1209
1210 do {
1211 *d += c; c = ( *d < c ); d++;
1212 }
1213 while( c != 0 );
1214}
1215
1216/*
1217 * Baseline multiplication: X = A * B (HAC 14.12)
1218 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001219int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001220{
Paul Bakker23986e52011-04-24 08:57:21 +00001221 int ret;
1222 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001223 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001224
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001225 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001227 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1228 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001229
Paul Bakker23986e52011-04-24 08:57:21 +00001230 for( i = A->n; i > 0; i-- )
1231 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001232 break;
1233
Paul Bakker23986e52011-04-24 08:57:21 +00001234 for( j = B->n; j > 0; j-- )
1235 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001236 break;
1237
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001238 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1239 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001240
Paul Bakker23986e52011-04-24 08:57:21 +00001241 for( i++; j > 0; j-- )
1242 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001243
1244 X->s = A->s * B->s;
1245
1246cleanup:
1247
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001248 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001249
1250 return( ret );
1251}
1252
1253/*
1254 * Baseline multiplication: X = A * b
1255 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001256int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001257{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001258 mbedtls_mpi _B;
1259 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001260
1261 _B.s = 1;
1262 _B.n = 1;
1263 _B.p = p;
1264 p[0] = b;
1265
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001266 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001267}
1268
1269/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001270 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1271 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001272 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001273static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1274 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001275{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001276#if defined(MBEDTLS_HAVE_UDBL)
1277 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001278#else
Simon Butcher9803d072016-01-03 00:24:34 +00001279 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1280 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001281 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1282 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001283 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001284#endif
1285
Simon Butcher15b15d12015-11-26 19:35:03 +00001286 /*
1287 * Check for overflow
1288 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001289 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001290 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001291 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001292
Simon Butcherf5ba0452015-12-27 23:01:55 +00001293 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001294 }
1295
1296#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001297 dividend = (mbedtls_t_udbl) u1 << biL;
1298 dividend |= (mbedtls_t_udbl) u0;
1299 quotient = dividend / d;
1300 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1301 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1302
1303 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001304 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001305
1306 return (mbedtls_mpi_uint) quotient;
1307#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001308
1309 /*
1310 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1311 * Vol. 2 - Seminumerical Algorithms, Knuth
1312 */
1313
1314 /*
1315 * Normalize the divisor, d, and dividend, u0, u1
1316 */
1317 s = mbedtls_clz( d );
1318 d = d << s;
1319
1320 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001321 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001322 u0 = u0 << s;
1323
1324 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001325 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001326
1327 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001328 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001329
1330 /*
1331 * Find the first quotient and remainder
1332 */
1333 q1 = u1 / d1;
1334 r0 = u1 - d1 * q1;
1335
1336 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1337 {
1338 q1 -= 1;
1339 r0 += d1;
1340
1341 if ( r0 >= radix ) break;
1342 }
1343
Simon Butcherf5ba0452015-12-27 23:01:55 +00001344 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001345 q0 = rAX / d1;
1346 r0 = rAX - q0 * d1;
1347
1348 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1349 {
1350 q0 -= 1;
1351 r0 += d1;
1352
1353 if ( r0 >= radix ) break;
1354 }
1355
1356 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001357 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001358
1359 quotient = q1 * radix + q0;
1360
1361 return quotient;
1362#endif
1363}
1364
1365/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001367 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001368int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001369{
Paul Bakker23986e52011-04-24 08:57:21 +00001370 int ret;
1371 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001373
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001374 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1375 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001376
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001377 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1378 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001379
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001380 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001381 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001382 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1383 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001384 return( 0 );
1385 }
1386
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001387 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1388 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001389 X.s = Y.s = 1;
1390
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1392 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1393 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1394 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001395
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001396 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001397 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001398 {
1399 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1401 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001402 }
1403 else k = 0;
1404
1405 n = X.n - 1;
1406 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001407 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001409 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001410 {
1411 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001412 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001413 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001415
1416 for( i = n; i > t ; i-- )
1417 {
1418 if( X.p[i] >= Y.p[t] )
1419 Z.p[i - t - 1] = ~0;
1420 else
1421 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001422 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1423 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001424 }
1425
1426 Z.p[i - t - 1]++;
1427 do
1428 {
1429 Z.p[i - t - 1]--;
1430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001431 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001432 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001433 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001434 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001435
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001436 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001437 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1438 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001439 T2.p[2] = X.p[i];
1440 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001441 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001443 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1444 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1445 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001446
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001447 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001448 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001449 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1450 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1451 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001452 Z.p[i - t - 1]--;
1453 }
1454 }
1455
1456 if( Q != NULL )
1457 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001458 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001459 Q->s = A->s * B->s;
1460 }
1461
1462 if( R != NULL )
1463 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001464 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001465 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001468 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001469 R->s = 1;
1470 }
1471
1472cleanup:
1473
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001474 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1475 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001476
1477 return( ret );
1478}
1479
1480/*
1481 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001482 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001483int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001484{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001485 mbedtls_mpi _B;
1486 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001487
1488 p[0] = ( b < 0 ) ? -b : b;
1489 _B.s = ( b < 0 ) ? -1 : 1;
1490 _B.n = 1;
1491 _B.p = p;
1492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001493 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001494}
1495
1496/*
1497 * Modulo: R = A mod B
1498 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001499int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001500{
1501 int ret;
1502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001503 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1504 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001505
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001508 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1509 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1512 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001513
1514cleanup:
1515
1516 return( ret );
1517}
1518
1519/*
1520 * Modulo: r = A mod b
1521 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001522int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001523{
Paul Bakker23986e52011-04-24 08:57:21 +00001524 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001525 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001526
1527 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001528 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001529
1530 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001531 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001532
1533 /*
1534 * handle trivial cases
1535 */
1536 if( b == 1 )
1537 {
1538 *r = 0;
1539 return( 0 );
1540 }
1541
1542 if( b == 2 )
1543 {
1544 *r = A->p[0] & 1;
1545 return( 0 );
1546 }
1547
1548 /*
1549 * general case
1550 */
Paul Bakker23986e52011-04-24 08:57:21 +00001551 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001552 {
Paul Bakker23986e52011-04-24 08:57:21 +00001553 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001554 y = ( y << biH ) | ( x >> biH );
1555 z = y / b;
1556 y -= z * b;
1557
1558 x <<= biH;
1559 y = ( y << biH ) | ( x >> biH );
1560 z = y / b;
1561 y -= z * b;
1562 }
1563
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001564 /*
1565 * If A is negative, then the current y represents a negative value.
1566 * Flipping it to the positive side.
1567 */
1568 if( A->s < 0 && y != 0 )
1569 y = b - y;
1570
Paul Bakker5121ce52009-01-03 21:22:43 +00001571 *r = y;
1572
1573 return( 0 );
1574}
1575
1576/*
1577 * Fast Montgomery initialization (thanks to Tom St Denis)
1578 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001579static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001580{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001581 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001582 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001583
1584 x = m0;
1585 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001586
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001587 for( i = biL; i >= 8; i /= 2 )
1588 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001589
1590 *mm = ~x + 1;
1591}
1592
1593/*
1594 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1595 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001596static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001597 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001598{
Paul Bakker23986e52011-04-24 08:57:21 +00001599 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001600 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001601
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001602 if( T->n < N->n + 1 || T->p == NULL )
1603 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1604
Paul Bakker5121ce52009-01-03 21:22:43 +00001605 memset( T->p, 0, T->n * ciL );
1606
1607 d = T->p;
1608 n = N->n;
1609 m = ( B->n < n ) ? B->n : n;
1610
1611 for( i = 0; i < n; i++ )
1612 {
1613 /*
1614 * T = (T + u0*B + u1*N) / 2^biL
1615 */
1616 u0 = A->p[i];
1617 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1618
1619 mpi_mul_hlp( m, B->p, d, u0 );
1620 mpi_mul_hlp( n, N->p, d, u1 );
1621
1622 *d++ = u0; d[n + 1] = 0;
1623 }
1624
Paul Bakker66d5d072014-06-17 16:39:18 +02001625 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001627 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001628 mpi_sub_hlp( n, N->p, A->p );
1629 else
1630 /* prevent timing attacks */
1631 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001632
1633 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001634}
1635
1636/*
1637 * Montgomery reduction: A = A * R^-1 mod N
1638 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001639static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001640{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001641 mbedtls_mpi_uint z = 1;
1642 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001643
Paul Bakker8ddb6452013-02-27 14:56:33 +01001644 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001645 U.p = &z;
1646
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001647 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001648}
1649
1650/*
1651 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1652 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001653int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001654{
Paul Bakker23986e52011-04-24 08:57:21 +00001655 int ret;
1656 size_t wbits, wsize, one = 1;
1657 size_t i, j, nblimbs;
1658 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001659 mbedtls_mpi_uint ei, mm, state;
1660 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001661 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001662
Hanno Becker930ec7d2018-03-09 10:48:00 +00001663 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001664 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001665
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001666 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1667 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001668
1669 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001670 * Init temps and window size
1671 */
1672 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001673 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1674 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001675 memset( W, 0, sizeof( W ) );
1676
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001677 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001678
1679 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1680 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001682 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1683 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001684
Paul Bakker5121ce52009-01-03 21:22:43 +00001685 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001686 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1687 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1688 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001689
1690 /*
Paul Bakker50546922012-05-19 08:40:49 +00001691 * Compensate for negative A (and correct at the end)
1692 */
1693 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001694 if( neg )
1695 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001696 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001697 Apos.s = 1;
1698 A = &Apos;
1699 }
1700
1701 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001702 * If 1st call, pre-compute R^2 mod N
1703 */
1704 if( _RR == NULL || _RR->p == NULL )
1705 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001706 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1707 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1708 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001709
1710 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001711 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001712 }
1713 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001714 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001715
1716 /*
1717 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1718 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001719 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1720 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001721 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001722 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001723
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001724 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001725
1726 /*
1727 * X = R^2 * R^-1 mod N = R mod N
1728 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001729 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001730 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001731
1732 if( wsize > 1 )
1733 {
1734 /*
1735 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1736 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001737 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001738
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001739 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1740 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001741
1742 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001743 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001744
Paul Bakker5121ce52009-01-03 21:22:43 +00001745 /*
1746 * W[i] = W[i - 1] * W[1]
1747 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001748 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001749 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001750 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1751 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001752
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001753 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001754 }
1755 }
1756
1757 nblimbs = E->n;
1758 bufsize = 0;
1759 nbits = 0;
1760 wbits = 0;
1761 state = 0;
1762
1763 while( 1 )
1764 {
1765 if( bufsize == 0 )
1766 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001767 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001768 break;
1769
Paul Bakker0d7702c2013-10-29 16:18:35 +01001770 nblimbs--;
1771
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001772 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001773 }
1774
1775 bufsize--;
1776
1777 ei = (E->p[nblimbs] >> bufsize) & 1;
1778
1779 /*
1780 * skip leading 0s
1781 */
1782 if( ei == 0 && state == 0 )
1783 continue;
1784
1785 if( ei == 0 && state == 1 )
1786 {
1787 /*
1788 * out of window, square X
1789 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001790 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001791 continue;
1792 }
1793
1794 /*
1795 * add ei to current window
1796 */
1797 state = 2;
1798
1799 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001800 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001801
1802 if( nbits == wsize )
1803 {
1804 /*
1805 * X = X^wsize R^-1 mod N
1806 */
1807 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001808 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001809
1810 /*
1811 * X = X * W[wbits] R^-1 mod N
1812 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001813 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001814
1815 state--;
1816 nbits = 0;
1817 wbits = 0;
1818 }
1819 }
1820
1821 /*
1822 * process the remaining bits
1823 */
1824 for( i = 0; i < nbits; i++ )
1825 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001826 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001827
1828 wbits <<= 1;
1829
Paul Bakker66d5d072014-06-17 16:39:18 +02001830 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001831 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001832 }
1833
1834 /*
1835 * X = A^E * R * R^-1 mod N = A^E mod N
1836 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001837 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001838
Hanno Beckera4af1c42017-04-18 09:07:45 +01001839 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001840 {
1841 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001842 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001843 }
1844
Paul Bakker5121ce52009-01-03 21:22:43 +00001845cleanup:
1846
Paul Bakker66d5d072014-06-17 16:39:18 +02001847 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001848 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001849
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001850 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001851
Paul Bakker75a28602014-03-31 12:08:17 +02001852 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001853 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001854
1855 return( ret );
1856}
1857
Paul Bakker5121ce52009-01-03 21:22:43 +00001858/*
1859 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1860 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001861int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001862{
Paul Bakker23986e52011-04-24 08:57:21 +00001863 int ret;
1864 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001865 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001866
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001867 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001868
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001869 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1870 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001871
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001872 lz = mbedtls_mpi_lsb( &TA );
1873 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001874
Paul Bakker66d5d072014-06-17 16:39:18 +02001875 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001876 lz = lzt;
1877
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001878 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1879 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001880
Paul Bakker5121ce52009-01-03 21:22:43 +00001881 TA.s = TB.s = 1;
1882
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001883 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001884 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001885 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1886 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001887
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001888 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001889 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001890 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1891 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001892 }
1893 else
1894 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001895 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1896 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001897 }
1898 }
1899
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001900 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1901 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001902
1903cleanup:
1904
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001905 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001906
1907 return( ret );
1908}
1909
Paul Bakker33dc46b2014-04-30 16:11:39 +02001910/*
1911 * Fill X with size bytes of random.
1912 *
1913 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001914 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001915 * deterministic, eg for tests).
1916 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001917int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001918 int (*f_rng)(void *, unsigned char *, size_t),
1919 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001920{
Paul Bakker23986e52011-04-24 08:57:21 +00001921 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001922 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001923
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001924 if( size > MBEDTLS_MPI_MAX_SIZE )
1925 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001926
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001927 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1928 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001929
1930cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01001931 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001932 return( ret );
1933}
1934
Paul Bakker5121ce52009-01-03 21:22:43 +00001935/*
1936 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1937 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001938int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001939{
1940 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001941 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001942
Hanno Becker4bcb4912017-04-18 15:49:39 +01001943 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001944 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001946 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1947 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1948 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001949
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001950 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001951
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001952 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001953 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001954 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001955 goto cleanup;
1956 }
1957
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001958 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1959 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1960 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1961 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001962
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1964 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1965 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1966 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001967
1968 do
1969 {
1970 while( ( TU.p[0] & 1 ) == 0 )
1971 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001972 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001973
1974 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1975 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001976 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1977 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001978 }
1979
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001980 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1981 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001982 }
1983
1984 while( ( TV.p[0] & 1 ) == 0 )
1985 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001986 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001987
1988 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1989 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001990 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1991 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001992 }
1993
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001994 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1995 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001996 }
1997
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001998 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001999 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002000 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2001 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2002 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002003 }
2004 else
2005 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002006 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2007 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2008 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002009 }
2010 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002011 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002012
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002013 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2014 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002015
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2017 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002018
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002019 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002020
2021cleanup:
2022
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2024 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2025 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002026
2027 return( ret );
2028}
2029
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002030#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002031
Paul Bakker5121ce52009-01-03 21:22:43 +00002032static const int small_prime[] =
2033{
2034 3, 5, 7, 11, 13, 17, 19, 23,
2035 29, 31, 37, 41, 43, 47, 53, 59,
2036 61, 67, 71, 73, 79, 83, 89, 97,
2037 101, 103, 107, 109, 113, 127, 131, 137,
2038 139, 149, 151, 157, 163, 167, 173, 179,
2039 181, 191, 193, 197, 199, 211, 223, 227,
2040 229, 233, 239, 241, 251, 257, 263, 269,
2041 271, 277, 281, 283, 293, 307, 311, 313,
2042 317, 331, 337, 347, 349, 353, 359, 367,
2043 373, 379, 383, 389, 397, 401, 409, 419,
2044 421, 431, 433, 439, 443, 449, 457, 461,
2045 463, 467, 479, 487, 491, 499, 503, 509,
2046 521, 523, 541, 547, 557, 563, 569, 571,
2047 577, 587, 593, 599, 601, 607, 613, 617,
2048 619, 631, 641, 643, 647, 653, 659, 661,
2049 673, 677, 683, 691, 701, 709, 719, 727,
2050 733, 739, 743, 751, 757, 761, 769, 773,
2051 787, 797, 809, 811, 821, 823, 827, 829,
2052 839, 853, 857, 859, 863, 877, 881, 883,
2053 887, 907, 911, 919, 929, 937, 941, 947,
2054 953, 967, 971, 977, 983, 991, 997, -103
2055};
2056
2057/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002058 * Small divisors test (X must be positive)
2059 *
2060 * Return values:
2061 * 0: no small factor (possible prime, more tests needed)
2062 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002063 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002064 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002065 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002066static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002067{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002068 int ret = 0;
2069 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002070 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002071
Paul Bakker5121ce52009-01-03 21:22:43 +00002072 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002073 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002074
2075 for( i = 0; small_prime[i] > 0; i++ )
2076 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002077 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002078 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002079
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002080 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002081
2082 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002083 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002084 }
2085
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002086cleanup:
2087 return( ret );
2088}
2089
2090/*
2091 * Miller-Rabin pseudo-primality test (HAC 4.24)
2092 */
Janos Follath72d555d2018-09-03 14:45:23 +01002093static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002094 int (*f_rng)(void *, unsigned char *, size_t),
2095 void *p_rng )
2096{
Pascal Junodb99183d2015-03-11 16:49:45 +01002097 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002098 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002099 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002100
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002101 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2102 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002103
Paul Bakker5121ce52009-01-03 21:22:43 +00002104 /*
2105 * W = |X| - 1
2106 * R = W >> lsb( W )
2107 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002108 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2109 s = mbedtls_mpi_lsb( &W );
2110 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2111 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002112
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002113 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002114
Janos Follath72d555d2018-09-03 14:45:23 +01002115 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002116 {
2117 /*
2118 * pick a random A, 1 < A < |X| - 1
2119 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002120 count = 0;
2121 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002122 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002123
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002124 j = mbedtls_mpi_bitlen( &A );
2125 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002126 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002127 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002128 }
2129
2130 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002131 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002132 }
2133
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002134 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2135 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002136
2137 /*
2138 * A = A^R mod |X|
2139 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002140 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002141
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002142 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2143 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002144 continue;
2145
2146 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002147 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002148 {
2149 /*
2150 * A = A * A mod |X|
2151 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002152 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2153 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002154
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002155 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002156 break;
2157
2158 j++;
2159 }
2160
2161 /*
2162 * not prime if A != |X| - 1 or A == 1
2163 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002164 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2165 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002166 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002167 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002168 break;
2169 }
2170 }
2171
2172cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002173 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2174 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002175
2176 return( ret );
2177}
2178
2179/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002180 * Pseudo-primality test: small factors, then Miller-Rabin
2181 */
Darryl Green94759f62018-10-16 15:09:19 +01002182static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002183 int (*f_rng)(void *, unsigned char *, size_t),
2184 void *p_rng )
2185{
2186 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002187 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002188
2189 XX.s = 1;
2190 XX.n = X->n;
2191 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002193 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2194 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2195 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002196
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002197 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002198 return( 0 );
2199
2200 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2201 {
2202 if( ret == 1 )
2203 return( 0 );
2204
2205 return( ret );
2206 }
2207
Janos Follath72d555d2018-09-03 14:45:23 +01002208 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2209}
2210
2211/*
2212 * Pseudo-primality test, error probability 2^-80
2213 */
2214int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2215 int (*f_rng)(void *, unsigned char *, size_t),
2216 void *p_rng )
2217{
2218 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002219}
2220
2221/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002222 * Prime number generation
2223 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002224int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002225 int (*f_rng)(void *, unsigned char *, size_t),
2226 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002227{
Paul Bakker23986e52011-04-24 08:57:21 +00002228 int ret;
2229 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002230 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002231 mbedtls_mpi_uint r;
2232 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002233
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002234 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2235 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002236
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002237 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002238
2239 n = BITS_TO_LIMBS( nbits );
2240
Janos Follath72d555d2018-09-03 14:45:23 +01002241 /*
2242 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2243 */
2244 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2245 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2246 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2247
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002248 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002249
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002250 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002251 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002252
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002253 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002254
2255 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002256
2257 if( dh_flag == 0 )
2258 {
Janos Follath72d555d2018-09-03 14:45:23 +01002259 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002260 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002261 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002262 goto cleanup;
2263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002265 }
2266 }
2267 else
2268 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002269 /*
2270 * An necessary condition for Y and X = 2Y + 1 to be prime
2271 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2272 * Make sure it is satisfied, while keeping X = 3 mod 4
2273 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002274
2275 X->p[0] |= 2;
2276
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002277 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002278 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002279 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002280 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002281 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002282
2283 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002284 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2285 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002286
2287 while( 1 )
2288 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002289 /*
2290 * First, check small factors for X and Y
2291 * before doing Miller-Rabin on any of them
2292 */
2293 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2294 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002295 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2296 == 0 &&
2297 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2298 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002299 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002300 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002301 }
2302
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002303 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002304 goto cleanup;
2305
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002306 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002307 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002308 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2309 * so up Y by 6 and X by 12.
2310 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002311 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2312 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002313 }
2314 }
2315
2316cleanup:
2317
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002318 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002319
2320 return( ret );
2321}
2322
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002323#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002324
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002325#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002326
Paul Bakker23986e52011-04-24 08:57:21 +00002327#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002328
2329static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2330{
2331 { 693, 609, 21 },
2332 { 1764, 868, 28 },
2333 { 768454923, 542167814, 1 }
2334};
2335
Paul Bakker5121ce52009-01-03 21:22:43 +00002336/*
2337 * Checkup routine
2338 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002339int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002340{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002341 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002344 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2345 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002348 "EFE021C2645FD1DC586E69184AF4A31E" \
2349 "D5F53E93B5F123FA41680867BA110131" \
2350 "944FE7952E2517337780CB0DB80E61AA" \
2351 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2352
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002354 "B2E7EFD37075B9F03FF989C7C5051C20" \
2355 "34D2A323810251127E7BF8625A4F49A5" \
2356 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2357 "5B5C25763222FEFCCFC38B832366C29E" ) );
2358
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002360 "0066A198186C18C10B2F5ED9B522752A" \
2361 "9830B69916E535C8F047518A889A43A5" \
2362 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2363
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002364 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002366 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002367 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2368 "9E857EA95A03512E2BAE7391688D264A" \
2369 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2370 "8001B72E848A38CAE1C65F78E56ABDEF" \
2371 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2372 "ECF677152EF804370C1A305CAF3B5BF1" \
2373 "30879B56C61DE584A0F53A2447A51E" ) );
2374
2375 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002378 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002379 {
2380 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002381 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002382
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002383 ret = 1;
2384 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002385 }
2386
2387 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002388 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002390 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002392 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002393 "256567336059E52CAE22925474705F39A94" ) );
2394
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002395 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002396 "6613F26162223DF488E9CD48CC132C7A" \
2397 "0AC93C701B001B092E4E5B9F73BCD27B" \
2398 "9EE50D0657C77F374E903CDFA4C642" ) );
2399
2400 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002401 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002402
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002403 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2404 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002405 {
2406 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002407 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002408
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002409 ret = 1;
2410 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002411 }
2412
2413 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002414 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002415
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002416 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002417
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002418 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002419 "36E139AEA55215609D2816998ED020BB" \
2420 "BD96C37890F65171D948E9BC7CBAA4D9" \
2421 "325D24D6A3C12710F10A09FA08AB87" ) );
2422
2423 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002424 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002425
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002426 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002427 {
2428 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002429 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002430
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002431 ret = 1;
2432 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002433 }
2434
2435 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002436 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002437
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002438 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002439
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002441 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2442 "C3DBA76456363A10869622EAC2DD84EC" \
2443 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2444
2445 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002446 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002447
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002448 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002449 {
2450 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002451 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002452
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002453 ret = 1;
2454 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002455 }
2456
2457 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002458 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002459
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002460 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002461 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002462
Paul Bakker66d5d072014-06-17 16:39:18 +02002463 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002464 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002465 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2466 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002468 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002469
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002470 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002471 {
2472 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002474
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002475 ret = 1;
2476 goto cleanup;
2477 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002478 }
2479
2480 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002481 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002482
Paul Bakker5121ce52009-01-03 21:22:43 +00002483cleanup:
2484
2485 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002486 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002487
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002488 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2489 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002490
2491 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002492 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002493
2494 return( ret );
2495}
2496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002497#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002499#endif /* MBEDTLS_BIGNUM_C */