blob: 47bf1ef9792f06187cfaf3627aa4f8ec3e565295 [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{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100187 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000188 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
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100206 if( X->n < i )
207 {
208 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
209 }
210 else
211 {
212 memset( X->p + i, 0, ( X->n - i ) * ciL );
213 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000214
Paul Bakker5121ce52009-01-03 21:22:43 +0000215 memcpy( X->p, Y->p, i * ciL );
216
217cleanup:
218
219 return( ret );
220}
221
222/*
223 * Swap the contents of X and Y
224 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200225void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000226{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200227 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000228
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229 memcpy( &T, X, sizeof( mbedtls_mpi ) );
230 memcpy( X, Y, sizeof( mbedtls_mpi ) );
231 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000232}
233
234/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100235 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100236 * about whether the assignment was made or not.
237 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100238 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100240{
241 int ret = 0;
242 size_t i;
243
Pascal Junodb99183d2015-03-11 16:49:45 +0100244 /* make sure assign is 0 or 1 in a time-constant manner */
245 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100246
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100248
Paul Bakker66d5d072014-06-17 16:39:18 +0200249 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100250
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100251 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200252 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100253
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100254 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200255 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100256
257cleanup:
258 return( ret );
259}
260
261/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100262 * Conditionally swap X and Y, without leaking information
263 * about whether the swap was made or not.
264 * Here it is not ok to simply swap the pointers, which whould lead to
265 * different memory access patterns when X and Y are used afterwards.
266 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100268{
269 int ret, s;
270 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200271 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100272
273 if( X == Y )
274 return( 0 );
275
Pascal Junodb99183d2015-03-11 16:49:45 +0100276 /* make sure swap is 0 or 1 in a time-constant manner */
277 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100278
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
280 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100281
282 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200283 X->s = X->s * ( 1 - swap ) + Y->s * swap;
284 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100285
286
287 for( i = 0; i < X->n; i++ )
288 {
289 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200290 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
291 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100292 }
293
294cleanup:
295 return( ret );
296}
297
298/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000299 * Set value from integer
300 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200301int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000302{
303 int ret;
304
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200305 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000306 memset( X->p, 0, X->n * ciL );
307
308 X->p[0] = ( z < 0 ) ? -z : z;
309 X->s = ( z < 0 ) ? -1 : 1;
310
311cleanup:
312
313 return( ret );
314}
315
316/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000317 * Get a specific bit
318 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200319int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000320{
321 if( X->n * biL <= pos )
322 return( 0 );
323
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200324 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000325}
326
327/*
328 * Set a bit to a specific value of 0 or 1
329 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200330int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000331{
332 int ret = 0;
333 size_t off = pos / biL;
334 size_t idx = pos % biL;
335
336 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200337 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200338
Paul Bakker2f5947e2011-05-18 15:47:11 +0000339 if( X->n * biL <= pos )
340 {
341 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200342 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000345 }
346
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
348 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000349
350cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200351
Paul Bakker2f5947e2011-05-18 15:47:11 +0000352 return( ret );
353}
354
355/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200356 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000357 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200358size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000359{
Paul Bakker23986e52011-04-24 08:57:21 +0000360 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000361
362 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000363 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000364 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
365 return( count );
366
367 return( 0 );
368}
369
370/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000371 * Count leading zero bits in a given integer
372 */
373static size_t mbedtls_clz( const mbedtls_mpi_uint x )
374{
375 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100376 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000377
378 for( j = 0; j < biL; j++ )
379 {
380 if( x & mask ) break;
381
382 mask >>= 1;
383 }
384
385 return j;
386}
387
388/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200389 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000390 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200391size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000392{
Paul Bakker23986e52011-04-24 08:57:21 +0000393 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000394
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200395 if( X->n == 0 )
396 return( 0 );
397
Paul Bakker5121ce52009-01-03 21:22:43 +0000398 for( i = X->n - 1; i > 0; i-- )
399 if( X->p[i] != 0 )
400 break;
401
Simon Butcher15b15d12015-11-26 19:35:03 +0000402 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000403
Paul Bakker23986e52011-04-24 08:57:21 +0000404 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000405}
406
407/*
408 * Return the total size in bytes
409 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200410size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000411{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200412 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000413}
414
415/*
416 * Convert an ASCII character to digit value
417 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200418static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000419{
420 *d = 255;
421
422 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
423 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
424 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
425
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200426 if( *d >= (mbedtls_mpi_uint) radix )
427 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000428
429 return( 0 );
430}
431
432/*
433 * Import from an ASCII string
434 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000436{
Paul Bakker23986e52011-04-24 08:57:21 +0000437 int ret;
438 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200439 mbedtls_mpi_uint d;
440 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000441
442 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200443 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000446
Paul Bakkerff60ee62010-03-16 21:09:09 +0000447 slen = strlen( s );
448
Paul Bakker5121ce52009-01-03 21:22:43 +0000449 if( radix == 16 )
450 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100451 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200452 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
453
Paul Bakkerff60ee62010-03-16 21:09:09 +0000454 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
457 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000458
Paul Bakker23986e52011-04-24 08:57:21 +0000459 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000460 {
Paul Bakker23986e52011-04-24 08:57:21 +0000461 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000462 {
463 X->s = -1;
464 break;
465 }
466
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200468 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000469 }
470 }
471 else
472 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200473 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000474
Paul Bakkerff60ee62010-03-16 21:09:09 +0000475 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000476 {
477 if( i == 0 && s[i] == '-' )
478 {
479 X->s = -1;
480 continue;
481 }
482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200483 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
484 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000485
486 if( X->s == 1 )
487 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200488 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000489 }
490 else
491 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000493 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000494 }
495 }
496
497cleanup:
498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000500
501 return( ret );
502}
503
504/*
505 * Helper to write the digits high-order first
506 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000508{
509 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000511
512 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000514
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
516 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000517
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
519 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000520
521 if( r < 10 )
522 *(*p)++ = (char)( r + 0x30 );
523 else
524 *(*p)++ = (char)( r + 0x37 );
525
526cleanup:
527
528 return( ret );
529}
530
531/*
532 * Export into an ASCII string
533 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100534int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
535 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000536{
Paul Bakker23986e52011-04-24 08:57:21 +0000537 int ret = 0;
538 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000539 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200540 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000541
542 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000544
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200545 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000546 if( radix >= 4 ) n >>= 1;
547 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000548 /*
549 * Round up the buffer length to an even value to ensure that there is
550 * enough room for hexadecimal values that can be represented in an odd
551 * number of digits.
552 */
553 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000554
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100555 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000556 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100557 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200558 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000559 }
560
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100561 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200562 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000563
564 if( X->s == -1 )
565 *p++ = '-';
566
567 if( radix == 16 )
568 {
Paul Bakker23986e52011-04-24 08:57:21 +0000569 int c;
570 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000571
Paul Bakker23986e52011-04-24 08:57:21 +0000572 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000573 {
Paul Bakker23986e52011-04-24 08:57:21 +0000574 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000575 {
Paul Bakker23986e52011-04-24 08:57:21 +0000576 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000577
Paul Bakker6c343d72014-07-10 14:36:19 +0200578 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000579 continue;
580
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000581 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000582 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000583 k = 1;
584 }
585 }
586 }
587 else
588 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200589 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000590
591 if( T.s == -1 )
592 T.s = 1;
593
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000595 }
596
597 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100598 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
600cleanup:
601
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000603
604 return( ret );
605}
606
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000608/*
609 * Read X from an opened file
610 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000612{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000614 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000615 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000616 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000617 * Buffer should have space for (short) label and decimal formatted MPI,
618 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000619 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000621
622 memset( s, 0, sizeof( s ) );
623 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200624 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000625
626 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000627 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000629
Hanno Beckerb2034b72017-04-26 11:46:46 +0100630 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
631 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000632
633 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100634 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000635 if( mpi_get_digit( &d, radix, *p ) != 0 )
636 break;
637
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000639}
640
641/*
642 * Write X into an opened file (or stdout if fout == NULL)
643 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200644int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000645{
Paul Bakker23986e52011-04-24 08:57:21 +0000646 int ret;
647 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000648 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000649 * Buffer should have space for (short) label and decimal formatted MPI,
650 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000651 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200652 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000653
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100654 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000655
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100656 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000657
658 if( p == NULL ) p = "";
659
660 plen = strlen( p );
661 slen = strlen( s );
662 s[slen++] = '\r';
663 s[slen++] = '\n';
664
665 if( fout != NULL )
666 {
667 if( fwrite( p, 1, plen, fout ) != plen ||
668 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000670 }
671 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000673
674cleanup:
675
676 return( ret );
677}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000679
680/*
681 * Import X from unsigned binary data, big endian
682 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000684{
Paul Bakker23986e52011-04-24 08:57:21 +0000685 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100686 size_t i, j;
687 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000688
Hanno Becker073c1992017-10-17 15:17:27 +0100689 /* Ensure that target MPI has exactly the necessary number of limbs */
690 if( X->n != limbs )
691 {
692 mbedtls_mpi_free( X );
693 mbedtls_mpi_init( X );
694 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
695 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
Hanno Becker073c1992017-10-17 15:17:27 +0100699 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200700 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000701
702cleanup:
703
704 return( ret );
705}
706
707/*
708 * Export X into unsigned binary data, big endian
709 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000711{
Paul Bakker23986e52011-04-24 08:57:21 +0000712 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000713
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000715
716 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200717 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000718
719 memset( buf, 0, buflen );
720
721 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
722 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
723
724 return( 0 );
725}
726
727/*
728 * Left-shift: X <<= count
729 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200730int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000731{
Paul Bakker23986e52011-04-24 08:57:21 +0000732 int ret;
733 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200734 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000735
736 v0 = count / (biL );
737 t1 = count & (biL - 1);
738
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200739 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000740
Paul Bakkerf9688572011-05-05 10:00:45 +0000741 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200742 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000743
744 ret = 0;
745
746 /*
747 * shift by count / limb_size
748 */
749 if( v0 > 0 )
750 {
Paul Bakker23986e52011-04-24 08:57:21 +0000751 for( i = X->n; i > v0; i-- )
752 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000753
Paul Bakker23986e52011-04-24 08:57:21 +0000754 for( ; i > 0; i-- )
755 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000756 }
757
758 /*
759 * shift by count % limb_size
760 */
761 if( t1 > 0 )
762 {
763 for( i = v0; i < X->n; i++ )
764 {
765 r1 = X->p[i] >> (biL - t1);
766 X->p[i] <<= t1;
767 X->p[i] |= r0;
768 r0 = r1;
769 }
770 }
771
772cleanup:
773
774 return( ret );
775}
776
777/*
778 * Right-shift: X >>= count
779 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200780int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000781{
Paul Bakker23986e52011-04-24 08:57:21 +0000782 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200783 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000784
785 v0 = count / biL;
786 v1 = count & (biL - 1);
787
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100788 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200789 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100790
Paul Bakker5121ce52009-01-03 21:22:43 +0000791 /*
792 * shift by count / limb_size
793 */
794 if( v0 > 0 )
795 {
796 for( i = 0; i < X->n - v0; i++ )
797 X->p[i] = X->p[i + v0];
798
799 for( ; i < X->n; i++ )
800 X->p[i] = 0;
801 }
802
803 /*
804 * shift by count % limb_size
805 */
806 if( v1 > 0 )
807 {
Paul Bakker23986e52011-04-24 08:57:21 +0000808 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000809 {
Paul Bakker23986e52011-04-24 08:57:21 +0000810 r1 = X->p[i - 1] << (biL - v1);
811 X->p[i - 1] >>= v1;
812 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000813 r0 = r1;
814 }
815 }
816
817 return( 0 );
818}
819
820/*
821 * Compare unsigned values
822 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200823int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000824{
Paul Bakker23986e52011-04-24 08:57:21 +0000825 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000826
Paul Bakker23986e52011-04-24 08:57:21 +0000827 for( i = X->n; i > 0; i-- )
828 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000829 break;
830
Paul Bakker23986e52011-04-24 08:57:21 +0000831 for( j = Y->n; j > 0; j-- )
832 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000833 break;
834
Paul Bakker23986e52011-04-24 08:57:21 +0000835 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000836 return( 0 );
837
838 if( i > j ) return( 1 );
839 if( j > i ) return( -1 );
840
Paul Bakker23986e52011-04-24 08:57:21 +0000841 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000842 {
Paul Bakker23986e52011-04-24 08:57:21 +0000843 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
844 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000845 }
846
847 return( 0 );
848}
849
850/*
851 * Compare signed values
852 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200853int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000854{
Paul Bakker23986e52011-04-24 08:57:21 +0000855 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000856
Paul Bakker23986e52011-04-24 08:57:21 +0000857 for( i = X->n; i > 0; i-- )
858 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000859 break;
860
Paul Bakker23986e52011-04-24 08:57:21 +0000861 for( j = Y->n; j > 0; j-- )
862 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000863 break;
864
Paul Bakker23986e52011-04-24 08:57:21 +0000865 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000866 return( 0 );
867
868 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000869 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000870
871 if( X->s > 0 && Y->s < 0 ) return( 1 );
872 if( Y->s > 0 && X->s < 0 ) return( -1 );
873
Paul Bakker23986e52011-04-24 08:57:21 +0000874 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000875 {
Paul Bakker23986e52011-04-24 08:57:21 +0000876 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
877 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000878 }
879
880 return( 0 );
881}
882
883/*
884 * Compare signed values
885 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200886int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000887{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200888 mbedtls_mpi Y;
889 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000890
891 *p = ( z < 0 ) ? -z : z;
892 Y.s = ( z < 0 ) ? -1 : 1;
893 Y.n = 1;
894 Y.p = p;
895
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200896 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000897}
898
899/*
900 * Unsigned addition: X = |A| + |B| (HAC 14.7)
901 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200902int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000903{
Paul Bakker23986e52011-04-24 08:57:21 +0000904 int ret;
905 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100906 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000907
908 if( X == B )
909 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200910 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000911 }
912
913 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200914 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200915
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000916 /*
917 * X should always be positive as a result of unsigned additions.
918 */
919 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000920
Paul Bakker23986e52011-04-24 08:57:21 +0000921 for( j = B->n; j > 0; j-- )
922 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000923 break;
924
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200925 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000926
927 o = B->p; p = X->p; c = 0;
928
Janos Follath6c922682015-10-30 17:43:11 +0100929 /*
930 * tmp is used because it might happen that p == o
931 */
Paul Bakker23986e52011-04-24 08:57:21 +0000932 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000933 {
Janos Follath6c922682015-10-30 17:43:11 +0100934 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000935 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100936 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000937 }
938
939 while( c != 0 )
940 {
941 if( i >= X->n )
942 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200943 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000944 p = X->p + i;
945 }
946
Paul Bakker2d319fd2012-09-16 21:34:26 +0000947 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000948 }
949
950cleanup:
951
952 return( ret );
953}
954
955/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200956 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000957 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200958static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000959{
Paul Bakker23986e52011-04-24 08:57:21 +0000960 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200961 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000962
963 for( i = c = 0; i < n; i++, s++, d++ )
964 {
965 z = ( *d < c ); *d -= c;
966 c = ( *d < *s ) + z; *d -= *s;
967 }
968
969 while( c != 0 )
970 {
971 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +0200972 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000973 }
974}
975
976/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100977 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000978 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200979int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000980{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200981 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000982 int ret;
983 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000984
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200985 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
986 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000987
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200988 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000989
990 if( X == B )
991 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200992 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000993 B = &TB;
994 }
995
996 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200997 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000998
Paul Bakker1ef7a532009-06-20 10:50:55 +0000999 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001000 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001001 */
1002 X->s = 1;
1003
Paul Bakker5121ce52009-01-03 21:22:43 +00001004 ret = 0;
1005
Paul Bakker23986e52011-04-24 08:57:21 +00001006 for( n = B->n; n > 0; n-- )
1007 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001008 break;
1009
Paul Bakker23986e52011-04-24 08:57:21 +00001010 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001011
1012cleanup:
1013
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001014 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001015
1016 return( ret );
1017}
1018
1019/*
1020 * Signed addition: X = A + B
1021 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001022int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001023{
1024 int ret, s = A->s;
1025
1026 if( A->s * B->s < 0 )
1027 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001028 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001029 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001030 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001031 X->s = s;
1032 }
1033 else
1034 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001035 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001036 X->s = -s;
1037 }
1038 }
1039 else
1040 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001041 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001042 X->s = s;
1043 }
1044
1045cleanup:
1046
1047 return( ret );
1048}
1049
1050/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001051 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001052 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001053int mbedtls_mpi_sub_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/*
1082 * Signed addition: X = A + b
1083 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001084int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001085{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001086 mbedtls_mpi _B;
1087 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001088
1089 p[0] = ( b < 0 ) ? -b : b;
1090 _B.s = ( b < 0 ) ? -1 : 1;
1091 _B.n = 1;
1092 _B.p = p;
1093
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001094 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001095}
1096
1097/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001098 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001099 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001100int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001101{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001102 mbedtls_mpi _B;
1103 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001104
1105 p[0] = ( b < 0 ) ? -b : b;
1106 _B.s = ( b < 0 ) ? -1 : 1;
1107 _B.n = 1;
1108 _B.p = p;
1109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001110 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001111}
1112
1113/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001114 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001115 */
1116static
1117#if defined(__APPLE__) && defined(__arm__)
1118/*
1119 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1120 * appears to need this to prevent bad ARM code generation at -O3.
1121 */
1122__attribute__ ((noinline))
1123#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001124void 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 +00001125{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001126 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001127
1128#if defined(MULADDC_HUIT)
1129 for( ; i >= 8; i -= 8 )
1130 {
1131 MULADDC_INIT
1132 MULADDC_HUIT
1133 MULADDC_STOP
1134 }
1135
1136 for( ; i > 0; i-- )
1137 {
1138 MULADDC_INIT
1139 MULADDC_CORE
1140 MULADDC_STOP
1141 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001142#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001143 for( ; i >= 16; i -= 16 )
1144 {
1145 MULADDC_INIT
1146 MULADDC_CORE MULADDC_CORE
1147 MULADDC_CORE MULADDC_CORE
1148 MULADDC_CORE MULADDC_CORE
1149 MULADDC_CORE MULADDC_CORE
1150
1151 MULADDC_CORE MULADDC_CORE
1152 MULADDC_CORE MULADDC_CORE
1153 MULADDC_CORE MULADDC_CORE
1154 MULADDC_CORE MULADDC_CORE
1155 MULADDC_STOP
1156 }
1157
1158 for( ; i >= 8; i -= 8 )
1159 {
1160 MULADDC_INIT
1161 MULADDC_CORE MULADDC_CORE
1162 MULADDC_CORE MULADDC_CORE
1163
1164 MULADDC_CORE MULADDC_CORE
1165 MULADDC_CORE MULADDC_CORE
1166 MULADDC_STOP
1167 }
1168
1169 for( ; i > 0; i-- )
1170 {
1171 MULADDC_INIT
1172 MULADDC_CORE
1173 MULADDC_STOP
1174 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001175#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001176
1177 t++;
1178
1179 do {
1180 *d += c; c = ( *d < c ); d++;
1181 }
1182 while( c != 0 );
1183}
1184
1185/*
1186 * Baseline multiplication: X = A * B (HAC 14.12)
1187 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001188int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001189{
Paul Bakker23986e52011-04-24 08:57:21 +00001190 int ret;
1191 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001192 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001193
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001194 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001195
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001196 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1197 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001198
Paul Bakker23986e52011-04-24 08:57:21 +00001199 for( i = A->n; i > 0; i-- )
1200 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001201 break;
1202
Paul Bakker23986e52011-04-24 08:57:21 +00001203 for( j = B->n; j > 0; j-- )
1204 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001205 break;
1206
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001207 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1208 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001209
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001210 for( ; j > 0; j-- )
1211 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001212
1213 X->s = A->s * B->s;
1214
1215cleanup:
1216
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001217 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001218
1219 return( ret );
1220}
1221
1222/*
1223 * Baseline multiplication: X = A * b
1224 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001225int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001226{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001227 mbedtls_mpi _B;
1228 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001229
1230 _B.s = 1;
1231 _B.n = 1;
1232 _B.p = p;
1233 p[0] = b;
1234
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001235 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001236}
1237
1238/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001239 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1240 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001241 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001242static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1243 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001244{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001245#if defined(MBEDTLS_HAVE_UDBL)
1246 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001247#else
Simon Butcher9803d072016-01-03 00:24:34 +00001248 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1249 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001250 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1251 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001252 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001253#endif
1254
Simon Butcher15b15d12015-11-26 19:35:03 +00001255 /*
1256 * Check for overflow
1257 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001258 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001259 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001260 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001261
Simon Butcherf5ba0452015-12-27 23:01:55 +00001262 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001263 }
1264
1265#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001266 dividend = (mbedtls_t_udbl) u1 << biL;
1267 dividend |= (mbedtls_t_udbl) u0;
1268 quotient = dividend / d;
1269 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1270 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1271
1272 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001273 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001274
1275 return (mbedtls_mpi_uint) quotient;
1276#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001277
1278 /*
1279 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1280 * Vol. 2 - Seminumerical Algorithms, Knuth
1281 */
1282
1283 /*
1284 * Normalize the divisor, d, and dividend, u0, u1
1285 */
1286 s = mbedtls_clz( d );
1287 d = d << s;
1288
1289 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001290 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001291 u0 = u0 << s;
1292
1293 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001294 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001295
1296 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001297 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001298
1299 /*
1300 * Find the first quotient and remainder
1301 */
1302 q1 = u1 / d1;
1303 r0 = u1 - d1 * q1;
1304
1305 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1306 {
1307 q1 -= 1;
1308 r0 += d1;
1309
1310 if ( r0 >= radix ) break;
1311 }
1312
Simon Butcherf5ba0452015-12-27 23:01:55 +00001313 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001314 q0 = rAX / d1;
1315 r0 = rAX - q0 * d1;
1316
1317 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1318 {
1319 q0 -= 1;
1320 r0 += d1;
1321
1322 if ( r0 >= radix ) break;
1323 }
1324
1325 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001326 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001327
1328 quotient = q1 * radix + q0;
1329
1330 return quotient;
1331#endif
1332}
1333
1334/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001335 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001336 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001337int 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 +00001338{
Paul Bakker23986e52011-04-24 08:57:21 +00001339 int ret;
1340 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001341 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001343 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1344 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001346 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1347 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001349 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001350 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001351 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1352 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001353 return( 0 );
1354 }
1355
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001356 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1357 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001358 X.s = Y.s = 1;
1359
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001360 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1361 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1362 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1363 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001364
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001365 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001366 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001367 {
1368 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001369 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1370 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001371 }
1372 else k = 0;
1373
1374 n = X.n - 1;
1375 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001376 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001378 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001379 {
1380 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001381 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001382 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001383 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001384
1385 for( i = n; i > t ; i-- )
1386 {
1387 if( X.p[i] >= Y.p[t] )
1388 Z.p[i - t - 1] = ~0;
1389 else
1390 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001391 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1392 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001393 }
1394
1395 Z.p[i - t - 1]++;
1396 do
1397 {
1398 Z.p[i - t - 1]--;
1399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001401 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001402 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001404
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001405 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001406 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1407 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001408 T2.p[2] = X.p[i];
1409 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001410 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001411
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001412 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1413 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1414 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001415
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001416 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001417 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001418 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1419 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1420 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001421 Z.p[i - t - 1]--;
1422 }
1423 }
1424
1425 if( Q != NULL )
1426 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001427 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001428 Q->s = A->s * B->s;
1429 }
1430
1431 if( R != NULL )
1432 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001433 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001434 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001435 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001436
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001437 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001438 R->s = 1;
1439 }
1440
1441cleanup:
1442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001443 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1444 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001445
1446 return( ret );
1447}
1448
1449/*
1450 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001451 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001452int 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 +00001453{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001454 mbedtls_mpi _B;
1455 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001456
1457 p[0] = ( b < 0 ) ? -b : b;
1458 _B.s = ( b < 0 ) ? -1 : 1;
1459 _B.n = 1;
1460 _B.p = p;
1461
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001462 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001463}
1464
1465/*
1466 * Modulo: R = A mod B
1467 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001468int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001469{
1470 int ret;
1471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001472 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1473 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001474
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001475 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001476
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001477 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1478 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001479
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001480 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1481 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001482
1483cleanup:
1484
1485 return( ret );
1486}
1487
1488/*
1489 * Modulo: r = A mod b
1490 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001491int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001492{
Paul Bakker23986e52011-04-24 08:57:21 +00001493 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001494 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001495
1496 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001497 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001498
1499 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001500 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001501
1502 /*
1503 * handle trivial cases
1504 */
1505 if( b == 1 )
1506 {
1507 *r = 0;
1508 return( 0 );
1509 }
1510
1511 if( b == 2 )
1512 {
1513 *r = A->p[0] & 1;
1514 return( 0 );
1515 }
1516
1517 /*
1518 * general case
1519 */
Paul Bakker23986e52011-04-24 08:57:21 +00001520 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001521 {
Paul Bakker23986e52011-04-24 08:57:21 +00001522 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001523 y = ( y << biH ) | ( x >> biH );
1524 z = y / b;
1525 y -= z * b;
1526
1527 x <<= biH;
1528 y = ( y << biH ) | ( x >> biH );
1529 z = y / b;
1530 y -= z * b;
1531 }
1532
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001533 /*
1534 * If A is negative, then the current y represents a negative value.
1535 * Flipping it to the positive side.
1536 */
1537 if( A->s < 0 && y != 0 )
1538 y = b - y;
1539
Paul Bakker5121ce52009-01-03 21:22:43 +00001540 *r = y;
1541
1542 return( 0 );
1543}
1544
1545/*
1546 * Fast Montgomery initialization (thanks to Tom St Denis)
1547 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001548static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001549{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001550 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001551 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001552
1553 x = m0;
1554 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001555
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001556 for( i = biL; i >= 8; i /= 2 )
1557 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001558
1559 *mm = ~x + 1;
1560}
1561
1562/*
1563 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1564 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001565static 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 +02001566 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001567{
Paul Bakker23986e52011-04-24 08:57:21 +00001568 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001569 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001570
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001571 if( T->n < N->n + 1 || T->p == NULL )
1572 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1573
Paul Bakker5121ce52009-01-03 21:22:43 +00001574 memset( T->p, 0, T->n * ciL );
1575
1576 d = T->p;
1577 n = N->n;
1578 m = ( B->n < n ) ? B->n : n;
1579
1580 for( i = 0; i < n; i++ )
1581 {
1582 /*
1583 * T = (T + u0*B + u1*N) / 2^biL
1584 */
1585 u0 = A->p[i];
1586 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1587
1588 mpi_mul_hlp( m, B->p, d, u0 );
1589 mpi_mul_hlp( n, N->p, d, u1 );
1590
1591 *d++ = u0; d[n + 1] = 0;
1592 }
1593
Paul Bakker66d5d072014-06-17 16:39:18 +02001594 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001595
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001596 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001597 mpi_sub_hlp( n, N->p, A->p );
1598 else
1599 /* prevent timing attacks */
1600 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001601
1602 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001603}
1604
1605/*
1606 * Montgomery reduction: A = A * R^-1 mod N
1607 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001608static 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 +00001609{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001610 mbedtls_mpi_uint z = 1;
1611 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001612
Paul Bakker8ddb6452013-02-27 14:56:33 +01001613 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001614 U.p = &z;
1615
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001616 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001617}
1618
1619/*
1620 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1621 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001622int 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 +00001623{
Paul Bakker23986e52011-04-24 08:57:21 +00001624 int ret;
1625 size_t wbits, wsize, one = 1;
1626 size_t i, j, nblimbs;
1627 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001628 mbedtls_mpi_uint ei, mm, state;
1629 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001630 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001631
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001632 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001633 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001635 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1636 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001637
1638 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001639 * Init temps and window size
1640 */
1641 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001642 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1643 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001644 memset( W, 0, sizeof( W ) );
1645
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001646 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001647
1648 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1649 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1650
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1652 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001653
Paul Bakker5121ce52009-01-03 21:22:43 +00001654 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001655 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1656 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1657 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001658
1659 /*
Paul Bakker50546922012-05-19 08:40:49 +00001660 * Compensate for negative A (and correct at the end)
1661 */
1662 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001663 if( neg )
1664 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001665 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001666 Apos.s = 1;
1667 A = &Apos;
1668 }
1669
1670 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001671 * If 1st call, pre-compute R^2 mod N
1672 */
1673 if( _RR == NULL || _RR->p == NULL )
1674 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001675 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1676 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1677 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001678
1679 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001680 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001681 }
1682 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001683 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001684
1685 /*
1686 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1687 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1689 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001690 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001691 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001692
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001693 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001694
1695 /*
1696 * X = R^2 * R^-1 mod N = R mod N
1697 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001698 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001699 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001700
1701 if( wsize > 1 )
1702 {
1703 /*
1704 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1705 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001706 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001707
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001708 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1709 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001710
1711 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001712 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001713
Paul Bakker5121ce52009-01-03 21:22:43 +00001714 /*
1715 * W[i] = W[i - 1] * W[1]
1716 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001717 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001718 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001719 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1720 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001721
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001722 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001723 }
1724 }
1725
1726 nblimbs = E->n;
1727 bufsize = 0;
1728 nbits = 0;
1729 wbits = 0;
1730 state = 0;
1731
1732 while( 1 )
1733 {
1734 if( bufsize == 0 )
1735 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001736 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001737 break;
1738
Paul Bakker0d7702c2013-10-29 16:18:35 +01001739 nblimbs--;
1740
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001741 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001742 }
1743
1744 bufsize--;
1745
1746 ei = (E->p[nblimbs] >> bufsize) & 1;
1747
1748 /*
1749 * skip leading 0s
1750 */
1751 if( ei == 0 && state == 0 )
1752 continue;
1753
1754 if( ei == 0 && state == 1 )
1755 {
1756 /*
1757 * out of window, square X
1758 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001759 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001760 continue;
1761 }
1762
1763 /*
1764 * add ei to current window
1765 */
1766 state = 2;
1767
1768 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001769 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001770
1771 if( nbits == wsize )
1772 {
1773 /*
1774 * X = X^wsize R^-1 mod N
1775 */
1776 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001777 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001778
1779 /*
1780 * X = X * W[wbits] R^-1 mod N
1781 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001782 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001783
1784 state--;
1785 nbits = 0;
1786 wbits = 0;
1787 }
1788 }
1789
1790 /*
1791 * process the remaining bits
1792 */
1793 for( i = 0; i < nbits; i++ )
1794 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001795 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001796
1797 wbits <<= 1;
1798
Paul Bakker66d5d072014-06-17 16:39:18 +02001799 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001800 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001801 }
1802
1803 /*
1804 * X = A^E * R * R^-1 mod N = A^E mod N
1805 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001806 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001807
Hanno Beckera4af1c42017-04-18 09:07:45 +01001808 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001809 {
1810 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001811 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001812 }
1813
Paul Bakker5121ce52009-01-03 21:22:43 +00001814cleanup:
1815
Paul Bakker66d5d072014-06-17 16:39:18 +02001816 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001817 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001818
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001819 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001820
Paul Bakker75a28602014-03-31 12:08:17 +02001821 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001822 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001823
1824 return( ret );
1825}
1826
Paul Bakker5121ce52009-01-03 21:22:43 +00001827/*
1828 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1829 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001831{
Paul Bakker23986e52011-04-24 08:57:21 +00001832 int ret;
1833 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001834 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001835
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001836 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001837
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001838 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1839 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001840
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001841 lz = mbedtls_mpi_lsb( &TA );
1842 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001843
Paul Bakker66d5d072014-06-17 16:39:18 +02001844 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001845 lz = lzt;
1846
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001847 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1848 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001849
Paul Bakker5121ce52009-01-03 21:22:43 +00001850 TA.s = TB.s = 1;
1851
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001852 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001853 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001854 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1855 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001856
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001857 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001858 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001859 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1860 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001861 }
1862 else
1863 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001864 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1865 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001866 }
1867 }
1868
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001869 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1870 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001871
1872cleanup:
1873
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001874 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001875
1876 return( ret );
1877}
1878
Paul Bakker33dc46b2014-04-30 16:11:39 +02001879/*
1880 * Fill X with size bytes of random.
1881 *
1882 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001883 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001884 * deterministic, eg for tests).
1885 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001886int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001887 int (*f_rng)(void *, unsigned char *, size_t),
1888 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001889{
Paul Bakker23986e52011-04-24 08:57:21 +00001890 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001891 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001892
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001893 if( size > MBEDTLS_MPI_MAX_SIZE )
1894 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001895
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001896 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1897 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001898
1899cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01001900 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001901 return( ret );
1902}
1903
Paul Bakker5121ce52009-01-03 21:22:43 +00001904/*
1905 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1906 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001907int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001908{
1909 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001910 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001911
Hanno Becker4bcb4912017-04-18 15:49:39 +01001912 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001913 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001914
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001915 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1916 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1917 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001918
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001919 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001920
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001921 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001922 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001923 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001924 goto cleanup;
1925 }
1926
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001927 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1928 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1929 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1930 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001931
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001932 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1933 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1934 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1935 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001936
1937 do
1938 {
1939 while( ( TU.p[0] & 1 ) == 0 )
1940 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001941 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001942
1943 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1944 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001945 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1946 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001947 }
1948
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001949 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1950 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001951 }
1952
1953 while( ( TV.p[0] & 1 ) == 0 )
1954 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001955 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956
1957 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1958 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1960 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001961 }
1962
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1964 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001965 }
1966
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001967 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001968 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001969 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1970 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1971 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001972 }
1973 else
1974 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001975 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1976 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1977 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001978 }
1979 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001980 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001981
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001982 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1983 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001984
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001985 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1986 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001987
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001989
1990cleanup:
1991
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001992 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1993 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1994 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001995
1996 return( ret );
1997}
1998
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001999#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002000
Paul Bakker5121ce52009-01-03 21:22:43 +00002001static const int small_prime[] =
2002{
2003 3, 5, 7, 11, 13, 17, 19, 23,
2004 29, 31, 37, 41, 43, 47, 53, 59,
2005 61, 67, 71, 73, 79, 83, 89, 97,
2006 101, 103, 107, 109, 113, 127, 131, 137,
2007 139, 149, 151, 157, 163, 167, 173, 179,
2008 181, 191, 193, 197, 199, 211, 223, 227,
2009 229, 233, 239, 241, 251, 257, 263, 269,
2010 271, 277, 281, 283, 293, 307, 311, 313,
2011 317, 331, 337, 347, 349, 353, 359, 367,
2012 373, 379, 383, 389, 397, 401, 409, 419,
2013 421, 431, 433, 439, 443, 449, 457, 461,
2014 463, 467, 479, 487, 491, 499, 503, 509,
2015 521, 523, 541, 547, 557, 563, 569, 571,
2016 577, 587, 593, 599, 601, 607, 613, 617,
2017 619, 631, 641, 643, 647, 653, 659, 661,
2018 673, 677, 683, 691, 701, 709, 719, 727,
2019 733, 739, 743, 751, 757, 761, 769, 773,
2020 787, 797, 809, 811, 821, 823, 827, 829,
2021 839, 853, 857, 859, 863, 877, 881, 883,
2022 887, 907, 911, 919, 929, 937, 941, 947,
2023 953, 967, 971, 977, 983, 991, 997, -103
2024};
2025
2026/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002027 * Small divisors test (X must be positive)
2028 *
2029 * Return values:
2030 * 0: no small factor (possible prime, more tests needed)
2031 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002032 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002033 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002034 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002035static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002036{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002037 int ret = 0;
2038 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002039 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002040
Paul Bakker5121ce52009-01-03 21:22:43 +00002041 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002042 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002043
2044 for( i = 0; small_prime[i] > 0; i++ )
2045 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002047 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002048
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002050
2051 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002053 }
2054
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002055cleanup:
2056 return( ret );
2057}
2058
2059/*
2060 * Miller-Rabin pseudo-primality test (HAC 4.24)
2061 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002062static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002063 int (*f_rng)(void *, unsigned char *, size_t),
2064 void *p_rng )
2065{
Pascal Junodb99183d2015-03-11 16:49:45 +01002066 int ret, count;
2067 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002068 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002069
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002070 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2071 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002072
Paul Bakker5121ce52009-01-03 21:22:43 +00002073 /*
2074 * W = |X| - 1
2075 * R = W >> lsb( W )
2076 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002077 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2078 s = mbedtls_mpi_lsb( &W );
2079 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2080 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002081
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002082 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002083 /*
2084 * HAC, table 4.4
2085 */
2086 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2087 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2088 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2089
2090 for( i = 0; i < n; i++ )
2091 {
2092 /*
2093 * pick a random A, 1 < A < |X| - 1
2094 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002095 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002096
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002097 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00002098 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002099 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002100 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00002101 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002102 A.p[0] |= 3;
2103
Pascal Junodb99183d2015-03-11 16:49:45 +01002104 count = 0;
2105 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002106 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002107
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002108 j = mbedtls_mpi_bitlen( &A );
2109 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002110 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002111 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002112 }
2113
2114 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002115 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002116 }
2117
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002118 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2119 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002120
2121 /*
2122 * A = A^R mod |X|
2123 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002124 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002125
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002126 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2127 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002128 continue;
2129
2130 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002131 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002132 {
2133 /*
2134 * A = A * A mod |X|
2135 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002136 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2137 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002138
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002139 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002140 break;
2141
2142 j++;
2143 }
2144
2145 /*
2146 * not prime if A != |X| - 1 or A == 1
2147 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002148 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2149 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002150 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002151 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002152 break;
2153 }
2154 }
2155
2156cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002157 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2158 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002159
2160 return( ret );
2161}
2162
2163/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002164 * Pseudo-primality test: small factors, then Miller-Rabin
2165 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002166int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002167 int (*f_rng)(void *, unsigned char *, size_t),
2168 void *p_rng )
2169{
2170 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002171 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002172
2173 XX.s = 1;
2174 XX.n = X->n;
2175 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2178 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2179 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002181 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002182 return( 0 );
2183
2184 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2185 {
2186 if( ret == 1 )
2187 return( 0 );
2188
2189 return( ret );
2190 }
2191
2192 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2193}
2194
2195/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002196 * Prime number generation
2197 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002199 int (*f_rng)(void *, unsigned char *, size_t),
2200 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002201{
Paul Bakker23986e52011-04-24 08:57:21 +00002202 int ret;
2203 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002204 mbedtls_mpi_uint r;
2205 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002206
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002207 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2208 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002210 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002211
2212 n = BITS_TO_LIMBS( nbits );
2213
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002214 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002215
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002216 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002217 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002218
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002219 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002220
2221 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002222
2223 if( dh_flag == 0 )
2224 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002225 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002226 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002227 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002228 goto cleanup;
2229
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002230 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002231 }
2232 }
2233 else
2234 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002235 /*
2236 * An necessary condition for Y and X = 2Y + 1 to be prime
2237 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2238 * Make sure it is satisfied, while keeping X = 3 mod 4
2239 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002240
2241 X->p[0] |= 2;
2242
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002243 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002244 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002245 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002246 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002247 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002248
2249 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002250 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2251 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002252
2253 while( 1 )
2254 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002255 /*
2256 * First, check small factors for X and Y
2257 * before doing Miller-Rabin on any of them
2258 */
2259 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2260 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2261 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2262 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002263 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002264 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002265 }
2266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002267 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002268 goto cleanup;
2269
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002270 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002271 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002272 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2273 * so up Y by 6 and X by 12.
2274 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002275 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2276 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002277 }
2278 }
2279
2280cleanup:
2281
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002282 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002283
2284 return( ret );
2285}
2286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002287#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002288
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002289#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002290
Paul Bakker23986e52011-04-24 08:57:21 +00002291#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002292
2293static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2294{
2295 { 693, 609, 21 },
2296 { 1764, 868, 28 },
2297 { 768454923, 542167814, 1 }
2298};
2299
Paul Bakker5121ce52009-01-03 21:22:43 +00002300/*
2301 * Checkup routine
2302 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002303int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002304{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002305 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002306 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002307
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002308 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2309 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002310
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002311 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002312 "EFE021C2645FD1DC586E69184AF4A31E" \
2313 "D5F53E93B5F123FA41680867BA110131" \
2314 "944FE7952E2517337780CB0DB80E61AA" \
2315 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2316
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002317 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002318 "B2E7EFD37075B9F03FF989C7C5051C20" \
2319 "34D2A323810251127E7BF8625A4F49A5" \
2320 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2321 "5B5C25763222FEFCCFC38B832366C29E" ) );
2322
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002323 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002324 "0066A198186C18C10B2F5ED9B522752A" \
2325 "9830B69916E535C8F047518A889A43A5" \
2326 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2327
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002328 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002329
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002331 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2332 "9E857EA95A03512E2BAE7391688D264A" \
2333 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2334 "8001B72E848A38CAE1C65F78E56ABDEF" \
2335 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2336 "ECF677152EF804370C1A305CAF3B5BF1" \
2337 "30879B56C61DE584A0F53A2447A51E" ) );
2338
2339 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002340 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002343 {
2344 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002345 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002347 ret = 1;
2348 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002349 }
2350
2351 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002352 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002354 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002355
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002356 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002357 "256567336059E52CAE22925474705F39A94" ) );
2358
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002360 "6613F26162223DF488E9CD48CC132C7A" \
2361 "0AC93C701B001B092E4E5B9F73BCD27B" \
2362 "9EE50D0657C77F374E903CDFA4C642" ) );
2363
2364 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002365 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002366
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2368 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002369 {
2370 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002371 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002372
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002373 ret = 1;
2374 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002375 }
2376
2377 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002378 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002379
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002380 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002381
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002382 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002383 "36E139AEA55215609D2816998ED020BB" \
2384 "BD96C37890F65171D948E9BC7CBAA4D9" \
2385 "325D24D6A3C12710F10A09FA08AB87" ) );
2386
2387 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002388 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002390 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002391 {
2392 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002393 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002394
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002395 ret = 1;
2396 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002397 }
2398
2399 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002400 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002401
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002402 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002403
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002404 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002405 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2406 "C3DBA76456363A10869622EAC2DD84EC" \
2407 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2408
2409 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002410 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002411
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002412 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002413 {
2414 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002415 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002416
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002417 ret = 1;
2418 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002419 }
2420
2421 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002422 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002423
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002424 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002425 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002426
Paul Bakker66d5d072014-06-17 16:39:18 +02002427 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002428 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002429 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2430 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002431
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002432 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002435 {
2436 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002437 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002438
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002439 ret = 1;
2440 goto cleanup;
2441 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002442 }
2443
2444 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002445 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002446
Paul Bakker5121ce52009-01-03 21:22:43 +00002447cleanup:
2448
2449 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002450 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002451
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002452 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2453 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002454
2455 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002456 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002457
2458 return( ret );
2459}
2460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002461#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002463#endif /* MBEDTLS_BIGNUM_C */