blob: fb748d8a1e0174469456549fe8fb4f5495f32eb9 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050048#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000049
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <string.h>
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020054#else
Rich Evans00ab4702015-02-06 13:43:58 +000055#include <stdio.h>
56#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020058#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020060#endif
61
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020062#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000063#define biL (ciL << 3) /* bits in limb */
64#define biH (ciL << 2) /* half limb size */
65
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010066#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
67
Paul Bakker5121ce52009-01-03 21:22:43 +000068/*
69 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020070 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000071 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020072#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
73#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000074
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050075/* Implementation that should never be optimized out by the compiler */
76static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) {
77 mbedtls_platform_zeroize( v, ciL * n );
78}
79
Paul Bakker5121ce52009-01-03 21:22:43 +000080/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000081 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000082 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020083void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000084{
Paul Bakker6c591fa2011-05-05 11:49:20 +000085 if( X == NULL )
86 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000087
Paul Bakker6c591fa2011-05-05 11:49:20 +000088 X->s = 1;
89 X->n = 0;
90 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000091}
92
93/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000094 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000095 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020096void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000097{
Paul Bakker6c591fa2011-05-05 11:49:20 +000098 if( X == NULL )
99 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000100
Paul Bakker6c591fa2011-05-05 11:49:20 +0000101 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200103 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200104 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000105 }
106
Paul Bakker6c591fa2011-05-05 11:49:20 +0000107 X->s = 1;
108 X->n = 0;
109 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000110}
111
112/*
113 * Enlarge to the specified number of limbs
114 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200115int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000116{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200117 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200120 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000121
Paul Bakker5121ce52009-01-03 21:22:43 +0000122 if( X->n < nblimbs )
123 {
Simon Butcher29176892016-05-20 00:19:09 +0100124 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200125 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000126
Paul Bakker5121ce52009-01-03 21:22:43 +0000127 if( X->p != NULL )
128 {
129 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200130 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000132 }
133
134 X->n = nblimbs;
135 X->p = p;
136 }
137
138 return( 0 );
139}
140
141/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100142 * Resize down as much as possible,
143 * while keeping at least the specified number of limbs
144 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100146{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200147 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100148 size_t i;
149
150 /* Actually resize up in this case */
151 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200152 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100153
154 for( i = X->n - 1; i > 0; i-- )
155 if( X->p[i] != 0 )
156 break;
157 i++;
158
159 if( i < nblimbs )
160 i = nblimbs;
161
Simon Butcher29176892016-05-20 00:19:09 +0100162 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200163 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100164
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100165 if( X->p != NULL )
166 {
167 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200168 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100170 }
171
172 X->n = i;
173 X->p = p;
174
175 return( 0 );
176}
177
178/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000179 * Copy the contents of Y into X
180 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000182{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100183 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000184 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000185
186 if( X == Y )
187 return( 0 );
188
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200189 if( Y->p == NULL )
190 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200192 return( 0 );
193 }
194
Paul Bakker5121ce52009-01-03 21:22:43 +0000195 for( i = Y->n - 1; i > 0; i-- )
196 if( Y->p[i] != 0 )
197 break;
198 i++;
199
200 X->s = Y->s;
201
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100202 if( X->n < i )
203 {
204 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
205 }
206 else
207 {
208 memset( X->p + i, 0, ( X->n - i ) * ciL );
209 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000210
Paul Bakker5121ce52009-01-03 21:22:43 +0000211 memcpy( X->p, Y->p, i * ciL );
212
213cleanup:
214
215 return( ret );
216}
217
218/*
219 * Swap the contents of X and Y
220 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000222{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200223 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000224
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200225 memcpy( &T, X, sizeof( mbedtls_mpi ) );
226 memcpy( X, Y, sizeof( mbedtls_mpi ) );
227 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000228}
229
230/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100231 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100232 * about whether the assignment was made or not.
233 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100234 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100236{
237 int ret = 0;
238 size_t i;
239
Pascal Junodb99183d2015-03-11 16:49:45 +0100240 /* make sure assign is 0 or 1 in a time-constant manner */
241 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100242
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200243 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100244
Paul Bakker66d5d072014-06-17 16:39:18 +0200245 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100246
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100247 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200248 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100249
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100250 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200251 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100252
253cleanup:
254 return( ret );
255}
256
257/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100258 * Conditionally swap X and Y, without leaking information
259 * about whether the swap was made or not.
260 * Here it is not ok to simply swap the pointers, which whould lead to
261 * different memory access patterns when X and Y are used afterwards.
262 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100264{
265 int ret, s;
266 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100268
269 if( X == Y )
270 return( 0 );
271
Pascal Junodb99183d2015-03-11 16:49:45 +0100272 /* make sure swap is 0 or 1 in a time-constant manner */
273 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200275 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
276 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100277
278 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200279 X->s = X->s * ( 1 - swap ) + Y->s * swap;
280 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100281
282
283 for( i = 0; i < X->n; i++ )
284 {
285 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200286 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
287 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100288 }
289
290cleanup:
291 return( ret );
292}
293
294/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000295 * Set value from integer
296 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200297int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000298{
299 int ret;
300
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200301 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000302 memset( X->p, 0, X->n * ciL );
303
304 X->p[0] = ( z < 0 ) ? -z : z;
305 X->s = ( z < 0 ) ? -1 : 1;
306
307cleanup:
308
309 return( ret );
310}
311
312/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000313 * Get a specific bit
314 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000316{
317 if( X->n * biL <= pos )
318 return( 0 );
319
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200320 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000321}
322
323/*
324 * Set a bit to a specific value of 0 or 1
325 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000327{
328 int ret = 0;
329 size_t off = pos / biL;
330 size_t idx = pos % biL;
331
332 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200333 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200334
Paul Bakker2f5947e2011-05-18 15:47:11 +0000335 if( X->n * biL <= pos )
336 {
337 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200338 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200340 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000341 }
342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200343 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
344 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000345
346cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200347
Paul Bakker2f5947e2011-05-18 15:47:11 +0000348 return( ret );
349}
350
351/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200352 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000353 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200354size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000355{
Paul Bakker23986e52011-04-24 08:57:21 +0000356 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000357
358 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000359 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000360 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
361 return( count );
362
363 return( 0 );
364}
365
366/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000367 * Count leading zero bits in a given integer
368 */
369static size_t mbedtls_clz( const mbedtls_mpi_uint x )
370{
371 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100372 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000373
374 for( j = 0; j < biL; j++ )
375 {
376 if( x & mask ) break;
377
378 mask >>= 1;
379 }
380
381 return j;
382}
383
384/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200385 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000386 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200387size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000388{
Paul Bakker23986e52011-04-24 08:57:21 +0000389 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000390
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200391 if( X->n == 0 )
392 return( 0 );
393
Paul Bakker5121ce52009-01-03 21:22:43 +0000394 for( i = X->n - 1; i > 0; i-- )
395 if( X->p[i] != 0 )
396 break;
397
Simon Butcher15b15d12015-11-26 19:35:03 +0000398 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000399
Paul Bakker23986e52011-04-24 08:57:21 +0000400 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000401}
402
403/*
404 * Return the total size in bytes
405 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000407{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200408 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000409}
410
411/*
412 * Convert an ASCII character to digit value
413 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200414static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000415{
416 *d = 255;
417
418 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
419 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
420 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
421
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200422 if( *d >= (mbedtls_mpi_uint) radix )
423 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000424
425 return( 0 );
426}
427
428/*
429 * Import from an ASCII string
430 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200431int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000432{
Paul Bakker23986e52011-04-24 08:57:21 +0000433 int ret;
434 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435 mbedtls_mpi_uint d;
436 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000437
438 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200439 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000440
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
Paul Bakkerff60ee62010-03-16 21:09:09 +0000443 slen = strlen( s );
444
Paul Bakker5121ce52009-01-03 21:22:43 +0000445 if( radix == 16 )
446 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100447 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200448 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
449
Paul Bakkerff60ee62010-03-16 21:09:09 +0000450 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000451
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
453 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000454
Paul Bakker23986e52011-04-24 08:57:21 +0000455 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000456 {
Paul Bakker23986e52011-04-24 08:57:21 +0000457 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 {
459 X->s = -1;
460 break;
461 }
462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200464 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000465 }
466 }
467 else
468 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200469 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000470
Paul Bakkerff60ee62010-03-16 21:09:09 +0000471 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000472 {
473 if( i == 0 && s[i] == '-' )
474 {
475 X->s = -1;
476 continue;
477 }
478
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
480 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000481
482 if( X->s == 1 )
483 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000485 }
486 else
487 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200488 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000489 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000490 }
491 }
492
493cleanup:
494
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200495 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000496
497 return( ret );
498}
499
500/*
501 * Helper to write the digits high-order first
502 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000504{
505 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200506 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000507
508 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200511 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
512 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
515 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000516
517 if( r < 10 )
518 *(*p)++ = (char)( r + 0x30 );
519 else
520 *(*p)++ = (char)( r + 0x37 );
521
522cleanup:
523
524 return( ret );
525}
526
527/*
528 * Export into an ASCII string
529 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100530int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
531 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000532{
Paul Bakker23986e52011-04-24 08:57:21 +0000533 int ret = 0;
534 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000535 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000537
538 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200539 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000540
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200541 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000542 if( radix >= 4 ) n >>= 1;
543 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000544 /*
545 * Round up the buffer length to an even value to ensure that there is
546 * enough room for hexadecimal values that can be represented in an odd
547 * number of digits.
548 */
549 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000550
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100551 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000552 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100553 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200554 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000555 }
556
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100557 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200558 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000559
560 if( X->s == -1 )
561 *p++ = '-';
562
563 if( radix == 16 )
564 {
Paul Bakker23986e52011-04-24 08:57:21 +0000565 int c;
566 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000567
Paul Bakker23986e52011-04-24 08:57:21 +0000568 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000569 {
Paul Bakker23986e52011-04-24 08:57:21 +0000570 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000571 {
Paul Bakker23986e52011-04-24 08:57:21 +0000572 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000573
Paul Bakker6c343d72014-07-10 14:36:19 +0200574 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000575 continue;
576
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000577 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000578 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000579 k = 1;
580 }
581 }
582 }
583 else
584 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200585 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000586
587 if( T.s == -1 )
588 T.s = 1;
589
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200590 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000591 }
592
593 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100594 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000595
596cleanup:
597
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
600 return( ret );
601}
602
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000604/*
605 * Read X from an opened file
606 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000608{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200609 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000610 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000611 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000612 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000613 * Buffer should have space for (short) label and decimal formatted MPI,
614 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000615 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200616 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000617
618 memset( s, 0, sizeof( s ) );
619 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000621
622 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000623 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200624 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000625
Hanno Beckerb2034b72017-04-26 11:46:46 +0100626 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
627 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000628
629 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100630 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000631 if( mpi_get_digit( &d, radix, *p ) != 0 )
632 break;
633
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200634 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000635}
636
637/*
638 * Write X into an opened file (or stdout if fout == NULL)
639 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200640int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000641{
Paul Bakker23986e52011-04-24 08:57:21 +0000642 int ret;
643 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000644 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000645 * Buffer should have space for (short) label and decimal formatted MPI,
646 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000647 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000649
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100650 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000651
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100652 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000653
654 if( p == NULL ) p = "";
655
656 plen = strlen( p );
657 slen = strlen( s );
658 s[slen++] = '\r';
659 s[slen++] = '\n';
660
661 if( fout != NULL )
662 {
663 if( fwrite( p, 1, plen, fout ) != plen ||
664 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000666 }
667 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200668 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000669
670cleanup:
671
672 return( ret );
673}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000675
676/*
677 * Import X from unsigned binary data, big endian
678 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200679int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000680{
Paul Bakker23986e52011-04-24 08:57:21 +0000681 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100682 size_t i, j;
683 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000684
Hanno Becker073c1992017-10-17 15:17:27 +0100685 /* Ensure that target MPI has exactly the necessary number of limbs */
686 if( X->n != limbs )
687 {
688 mbedtls_mpi_free( X );
689 mbedtls_mpi_init( X );
690 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
691 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000692
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200693 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000694
Hanno Becker073c1992017-10-17 15:17:27 +0100695 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000697
698cleanup:
699
700 return( ret );
701}
702
703/*
704 * Export X into unsigned binary data, big endian
705 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000707{
Paul Bakker23986e52011-04-24 08:57:21 +0000708 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000709
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
712 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200713 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000714
715 memset( buf, 0, buflen );
716
717 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
718 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
719
720 return( 0 );
721}
722
723/*
724 * Left-shift: X <<= count
725 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200726int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000727{
Paul Bakker23986e52011-04-24 08:57:21 +0000728 int ret;
729 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200730 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000731
732 v0 = count / (biL );
733 t1 = count & (biL - 1);
734
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200735 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000736
Paul Bakkerf9688572011-05-05 10:00:45 +0000737 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200738 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000739
740 ret = 0;
741
742 /*
743 * shift by count / limb_size
744 */
745 if( v0 > 0 )
746 {
Paul Bakker23986e52011-04-24 08:57:21 +0000747 for( i = X->n; i > v0; i-- )
748 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000749
Paul Bakker23986e52011-04-24 08:57:21 +0000750 for( ; i > 0; i-- )
751 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000752 }
753
754 /*
755 * shift by count % limb_size
756 */
757 if( t1 > 0 )
758 {
759 for( i = v0; i < X->n; i++ )
760 {
761 r1 = X->p[i] >> (biL - t1);
762 X->p[i] <<= t1;
763 X->p[i] |= r0;
764 r0 = r1;
765 }
766 }
767
768cleanup:
769
770 return( ret );
771}
772
773/*
774 * Right-shift: X >>= count
775 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200776int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000777{
Paul Bakker23986e52011-04-24 08:57:21 +0000778 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200779 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000780
781 v0 = count / biL;
782 v1 = count & (biL - 1);
783
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100784 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200785 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100786
Paul Bakker5121ce52009-01-03 21:22:43 +0000787 /*
788 * shift by count / limb_size
789 */
790 if( v0 > 0 )
791 {
792 for( i = 0; i < X->n - v0; i++ )
793 X->p[i] = X->p[i + v0];
794
795 for( ; i < X->n; i++ )
796 X->p[i] = 0;
797 }
798
799 /*
800 * shift by count % limb_size
801 */
802 if( v1 > 0 )
803 {
Paul Bakker23986e52011-04-24 08:57:21 +0000804 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000805 {
Paul Bakker23986e52011-04-24 08:57:21 +0000806 r1 = X->p[i - 1] << (biL - v1);
807 X->p[i - 1] >>= v1;
808 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000809 r0 = r1;
810 }
811 }
812
813 return( 0 );
814}
815
816/*
817 * Compare unsigned values
818 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200819int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000820{
Paul Bakker23986e52011-04-24 08:57:21 +0000821 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000822
Paul Bakker23986e52011-04-24 08:57:21 +0000823 for( i = X->n; i > 0; i-- )
824 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000825 break;
826
Paul Bakker23986e52011-04-24 08:57:21 +0000827 for( j = Y->n; j > 0; j-- )
828 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000829 break;
830
Paul Bakker23986e52011-04-24 08:57:21 +0000831 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000832 return( 0 );
833
834 if( i > j ) return( 1 );
835 if( j > i ) return( -1 );
836
Paul Bakker23986e52011-04-24 08:57:21 +0000837 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000838 {
Paul Bakker23986e52011-04-24 08:57:21 +0000839 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
840 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000841 }
842
843 return( 0 );
844}
845
846/*
847 * Compare signed values
848 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200849int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000850{
Paul Bakker23986e52011-04-24 08:57:21 +0000851 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000852
Paul Bakker23986e52011-04-24 08:57:21 +0000853 for( i = X->n; i > 0; i-- )
854 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000855 break;
856
Paul Bakker23986e52011-04-24 08:57:21 +0000857 for( j = Y->n; j > 0; j-- )
858 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000859 break;
860
Paul Bakker23986e52011-04-24 08:57:21 +0000861 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000862 return( 0 );
863
864 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000865 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000866
867 if( X->s > 0 && Y->s < 0 ) return( 1 );
868 if( Y->s > 0 && X->s < 0 ) return( -1 );
869
Paul Bakker23986e52011-04-24 08:57:21 +0000870 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000871 {
Paul Bakker23986e52011-04-24 08:57:21 +0000872 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
873 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000874 }
875
876 return( 0 );
877}
878
879/*
880 * Compare signed values
881 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200882int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000883{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200884 mbedtls_mpi Y;
885 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000886
887 *p = ( z < 0 ) ? -z : z;
888 Y.s = ( z < 0 ) ? -1 : 1;
889 Y.n = 1;
890 Y.p = p;
891
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200892 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000893}
894
895/*
896 * Unsigned addition: X = |A| + |B| (HAC 14.7)
897 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200898int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000899{
Paul Bakker23986e52011-04-24 08:57:21 +0000900 int ret;
901 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100902 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000903
904 if( X == B )
905 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200906 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000907 }
908
909 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200910 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200911
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000912 /*
913 * X should always be positive as a result of unsigned additions.
914 */
915 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000916
Paul Bakker23986e52011-04-24 08:57:21 +0000917 for( j = B->n; j > 0; j-- )
918 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000919 break;
920
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200921 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000922
923 o = B->p; p = X->p; c = 0;
924
Janos Follath6c922682015-10-30 17:43:11 +0100925 /*
926 * tmp is used because it might happen that p == o
927 */
Paul Bakker23986e52011-04-24 08:57:21 +0000928 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000929 {
Janos Follath6c922682015-10-30 17:43:11 +0100930 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000931 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100932 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000933 }
934
935 while( c != 0 )
936 {
937 if( i >= X->n )
938 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200939 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000940 p = X->p + i;
941 }
942
Paul Bakker2d319fd2012-09-16 21:34:26 +0000943 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000944 }
945
946cleanup:
947
948 return( ret );
949}
950
951/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200952 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000953 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200954static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000955{
Paul Bakker23986e52011-04-24 08:57:21 +0000956 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200957 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000958
959 for( i = c = 0; i < n; i++, s++, d++ )
960 {
961 z = ( *d < c ); *d -= c;
962 c = ( *d < *s ) + z; *d -= *s;
963 }
964
965 while( c != 0 )
966 {
967 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +0200968 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000969 }
970}
971
972/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100973 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000974 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200975int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000976{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000978 int ret;
979 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000980
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200981 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
982 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000983
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200984 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000985
986 if( X == B )
987 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200988 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000989 B = &TB;
990 }
991
992 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200993 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000994
Paul Bakker1ef7a532009-06-20 10:50:55 +0000995 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100996 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000997 */
998 X->s = 1;
999
Paul Bakker5121ce52009-01-03 21:22:43 +00001000 ret = 0;
1001
Paul Bakker23986e52011-04-24 08:57:21 +00001002 for( n = B->n; n > 0; n-- )
1003 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001004 break;
1005
Paul Bakker23986e52011-04-24 08:57:21 +00001006 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001007
1008cleanup:
1009
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001010 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001011
1012 return( ret );
1013}
1014
1015/*
1016 * Signed addition: X = A + B
1017 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001018int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001019{
1020 int ret, s = A->s;
1021
1022 if( A->s * B->s < 0 )
1023 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001024 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001025 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001026 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001027 X->s = s;
1028 }
1029 else
1030 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001031 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001032 X->s = -s;
1033 }
1034 }
1035 else
1036 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001037 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001038 X->s = s;
1039 }
1040
1041cleanup:
1042
1043 return( ret );
1044}
1045
1046/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001047 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001048 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001049int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001050{
1051 int ret, s = A->s;
1052
1053 if( A->s * B->s > 0 )
1054 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001055 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001056 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001057 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001058 X->s = s;
1059 }
1060 else
1061 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001062 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001063 X->s = -s;
1064 }
1065 }
1066 else
1067 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001068 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001069 X->s = s;
1070 }
1071
1072cleanup:
1073
1074 return( ret );
1075}
1076
1077/*
1078 * Signed addition: X = A + b
1079 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001080int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001081{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001082 mbedtls_mpi _B;
1083 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001084
1085 p[0] = ( b < 0 ) ? -b : b;
1086 _B.s = ( b < 0 ) ? -1 : 1;
1087 _B.n = 1;
1088 _B.p = p;
1089
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001090 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001091}
1092
1093/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001094 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001095 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001096int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001097{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001098 mbedtls_mpi _B;
1099 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001100
1101 p[0] = ( b < 0 ) ? -b : b;
1102 _B.s = ( b < 0 ) ? -1 : 1;
1103 _B.n = 1;
1104 _B.p = p;
1105
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001106 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001107}
1108
1109/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001110 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001111 */
1112static
1113#if defined(__APPLE__) && defined(__arm__)
1114/*
1115 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1116 * appears to need this to prevent bad ARM code generation at -O3.
1117 */
1118__attribute__ ((noinline))
1119#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001120void 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 +00001121{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001122 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001123
1124#if defined(MULADDC_HUIT)
1125 for( ; i >= 8; i -= 8 )
1126 {
1127 MULADDC_INIT
1128 MULADDC_HUIT
1129 MULADDC_STOP
1130 }
1131
1132 for( ; i > 0; i-- )
1133 {
1134 MULADDC_INIT
1135 MULADDC_CORE
1136 MULADDC_STOP
1137 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001138#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001139 for( ; i >= 16; i -= 16 )
1140 {
1141 MULADDC_INIT
1142 MULADDC_CORE MULADDC_CORE
1143 MULADDC_CORE MULADDC_CORE
1144 MULADDC_CORE MULADDC_CORE
1145 MULADDC_CORE MULADDC_CORE
1146
1147 MULADDC_CORE MULADDC_CORE
1148 MULADDC_CORE MULADDC_CORE
1149 MULADDC_CORE MULADDC_CORE
1150 MULADDC_CORE MULADDC_CORE
1151 MULADDC_STOP
1152 }
1153
1154 for( ; i >= 8; i -= 8 )
1155 {
1156 MULADDC_INIT
1157 MULADDC_CORE MULADDC_CORE
1158 MULADDC_CORE MULADDC_CORE
1159
1160 MULADDC_CORE MULADDC_CORE
1161 MULADDC_CORE MULADDC_CORE
1162 MULADDC_STOP
1163 }
1164
1165 for( ; i > 0; i-- )
1166 {
1167 MULADDC_INIT
1168 MULADDC_CORE
1169 MULADDC_STOP
1170 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001171#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001172
1173 t++;
1174
1175 do {
1176 *d += c; c = ( *d < c ); d++;
1177 }
1178 while( c != 0 );
1179}
1180
1181/*
1182 * Baseline multiplication: X = A * B (HAC 14.12)
1183 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001184int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001185{
Paul Bakker23986e52011-04-24 08:57:21 +00001186 int ret;
1187 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001188 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001189
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001190 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001192 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1193 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001194
Paul Bakker23986e52011-04-24 08:57:21 +00001195 for( i = A->n; i > 0; i-- )
1196 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001197 break;
1198
Paul Bakker23986e52011-04-24 08:57:21 +00001199 for( j = B->n; j > 0; j-- )
1200 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001201 break;
1202
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001203 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1204 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001205
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001206 for( ; j > 0; j-- )
1207 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001208
1209 X->s = A->s * B->s;
1210
1211cleanup:
1212
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001213 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001214
1215 return( ret );
1216}
1217
1218/*
1219 * Baseline multiplication: X = A * b
1220 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001221int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001222{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001223 mbedtls_mpi _B;
1224 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001225
1226 _B.s = 1;
1227 _B.n = 1;
1228 _B.p = p;
1229 p[0] = b;
1230
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001231 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001232}
1233
1234/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001235 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1236 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001237 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001238static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1239 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001240{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001241#if defined(MBEDTLS_HAVE_UDBL)
1242 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001243#else
Simon Butcher9803d072016-01-03 00:24:34 +00001244 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1245 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001246 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1247 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001248 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001249#endif
1250
Simon Butcher15b15d12015-11-26 19:35:03 +00001251 /*
1252 * Check for overflow
1253 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001254 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001255 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001256 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001257
Simon Butcherf5ba0452015-12-27 23:01:55 +00001258 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001259 }
1260
1261#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001262 dividend = (mbedtls_t_udbl) u1 << biL;
1263 dividend |= (mbedtls_t_udbl) u0;
1264 quotient = dividend / d;
1265 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1266 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1267
1268 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001269 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001270
1271 return (mbedtls_mpi_uint) quotient;
1272#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001273
1274 /*
1275 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1276 * Vol. 2 - Seminumerical Algorithms, Knuth
1277 */
1278
1279 /*
1280 * Normalize the divisor, d, and dividend, u0, u1
1281 */
1282 s = mbedtls_clz( d );
1283 d = d << s;
1284
1285 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001286 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001287 u0 = u0 << s;
1288
1289 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001290 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001291
1292 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001293 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001294
1295 /*
1296 * Find the first quotient and remainder
1297 */
1298 q1 = u1 / d1;
1299 r0 = u1 - d1 * q1;
1300
1301 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1302 {
1303 q1 -= 1;
1304 r0 += d1;
1305
1306 if ( r0 >= radix ) break;
1307 }
1308
Simon Butcherf5ba0452015-12-27 23:01:55 +00001309 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001310 q0 = rAX / d1;
1311 r0 = rAX - q0 * d1;
1312
1313 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1314 {
1315 q0 -= 1;
1316 r0 += d1;
1317
1318 if ( r0 >= radix ) break;
1319 }
1320
1321 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001322 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001323
1324 quotient = q1 * radix + q0;
1325
1326 return quotient;
1327#endif
1328}
1329
1330/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001331 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001332 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001333int 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 +00001334{
Paul Bakker23986e52011-04-24 08:57:21 +00001335 int ret;
1336 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001337 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001338
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001339 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1340 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001342 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1343 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001345 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001346 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001347 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1348 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001349 return( 0 );
1350 }
1351
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001352 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1353 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001354 X.s = Y.s = 1;
1355
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001356 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1357 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1358 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1359 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001360
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001361 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001362 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001363 {
1364 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1366 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001367 }
1368 else k = 0;
1369
1370 n = X.n - 1;
1371 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001373
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001374 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001375 {
1376 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001377 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001378 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001379 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001380
1381 for( i = n; i > t ; i-- )
1382 {
1383 if( X.p[i] >= Y.p[t] )
1384 Z.p[i - t - 1] = ~0;
1385 else
1386 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001387 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1388 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001389 }
1390
1391 Z.p[i - t - 1]++;
1392 do
1393 {
1394 Z.p[i - t - 1]--;
1395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001396 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001397 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001398 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001400
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001401 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001402 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1403 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001404 T2.p[2] = X.p[i];
1405 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001408 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1409 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1410 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001411
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001412 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001413 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1415 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1416 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001417 Z.p[i - t - 1]--;
1418 }
1419 }
1420
1421 if( Q != NULL )
1422 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001423 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001424 Q->s = A->s * B->s;
1425 }
1426
1427 if( R != NULL )
1428 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001429 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001430 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001431 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001432
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001433 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001434 R->s = 1;
1435 }
1436
1437cleanup:
1438
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001439 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1440 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001441
1442 return( ret );
1443}
1444
1445/*
1446 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001447 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001448int 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 +00001449{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001450 mbedtls_mpi _B;
1451 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001452
1453 p[0] = ( b < 0 ) ? -b : b;
1454 _B.s = ( b < 0 ) ? -1 : 1;
1455 _B.n = 1;
1456 _B.p = p;
1457
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001458 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001459}
1460
1461/*
1462 * Modulo: R = A mod B
1463 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001464int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001465{
1466 int ret;
1467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001468 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1469 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001473 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1474 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001475
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001476 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1477 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001478
1479cleanup:
1480
1481 return( ret );
1482}
1483
1484/*
1485 * Modulo: r = A mod b
1486 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001487int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001488{
Paul Bakker23986e52011-04-24 08:57:21 +00001489 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001490 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001491
1492 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001493 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001494
1495 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001496 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001497
1498 /*
1499 * handle trivial cases
1500 */
1501 if( b == 1 )
1502 {
1503 *r = 0;
1504 return( 0 );
1505 }
1506
1507 if( b == 2 )
1508 {
1509 *r = A->p[0] & 1;
1510 return( 0 );
1511 }
1512
1513 /*
1514 * general case
1515 */
Paul Bakker23986e52011-04-24 08:57:21 +00001516 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001517 {
Paul Bakker23986e52011-04-24 08:57:21 +00001518 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001519 y = ( y << biH ) | ( x >> biH );
1520 z = y / b;
1521 y -= z * b;
1522
1523 x <<= biH;
1524 y = ( y << biH ) | ( x >> biH );
1525 z = y / b;
1526 y -= z * b;
1527 }
1528
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001529 /*
1530 * If A is negative, then the current y represents a negative value.
1531 * Flipping it to the positive side.
1532 */
1533 if( A->s < 0 && y != 0 )
1534 y = b - y;
1535
Paul Bakker5121ce52009-01-03 21:22:43 +00001536 *r = y;
1537
1538 return( 0 );
1539}
1540
1541/*
1542 * Fast Montgomery initialization (thanks to Tom St Denis)
1543 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001544static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001545{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001546 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001547 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001548
1549 x = m0;
1550 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001551
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001552 for( i = biL; i >= 8; i /= 2 )
1553 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001554
1555 *mm = ~x + 1;
1556}
1557
1558/*
1559 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1560 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001561static 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 +02001562 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001563{
Paul Bakker23986e52011-04-24 08:57:21 +00001564 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001565 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001566
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001567 if( T->n < N->n + 1 || T->p == NULL )
1568 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1569
Paul Bakker5121ce52009-01-03 21:22:43 +00001570 memset( T->p, 0, T->n * ciL );
1571
1572 d = T->p;
1573 n = N->n;
1574 m = ( B->n < n ) ? B->n : n;
1575
1576 for( i = 0; i < n; i++ )
1577 {
1578 /*
1579 * T = (T + u0*B + u1*N) / 2^biL
1580 */
1581 u0 = A->p[i];
1582 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1583
1584 mpi_mul_hlp( m, B->p, d, u0 );
1585 mpi_mul_hlp( n, N->p, d, u1 );
1586
1587 *d++ = u0; d[n + 1] = 0;
1588 }
1589
Paul Bakker66d5d072014-06-17 16:39:18 +02001590 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001591
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001592 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001593 mpi_sub_hlp( n, N->p, A->p );
1594 else
1595 /* prevent timing attacks */
1596 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001597
1598 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001599}
1600
1601/*
1602 * Montgomery reduction: A = A * R^-1 mod N
1603 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001604static 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 +00001605{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001606 mbedtls_mpi_uint z = 1;
1607 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001608
Paul Bakker8ddb6452013-02-27 14:56:33 +01001609 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001610 U.p = &z;
1611
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001612 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001613}
1614
1615/*
1616 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1617 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001618int 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 +00001619{
Paul Bakker23986e52011-04-24 08:57:21 +00001620 int ret;
1621 size_t wbits, wsize, one = 1;
1622 size_t i, j, nblimbs;
1623 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001624 mbedtls_mpi_uint ei, mm, state;
1625 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001626 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001627
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001628 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001629 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001630
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001631 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1632 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001633
1634 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001635 * Init temps and window size
1636 */
1637 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001638 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1639 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001640 memset( W, 0, sizeof( W ) );
1641
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001642 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001643
1644 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1645 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1646
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001647 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1648 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001649
Paul Bakker5121ce52009-01-03 21:22:43 +00001650 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1652 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1653 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001654
1655 /*
Paul Bakker50546922012-05-19 08:40:49 +00001656 * Compensate for negative A (and correct at the end)
1657 */
1658 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001659 if( neg )
1660 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001662 Apos.s = 1;
1663 A = &Apos;
1664 }
1665
1666 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001667 * If 1st call, pre-compute R^2 mod N
1668 */
1669 if( _RR == NULL || _RR->p == NULL )
1670 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1672 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1673 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001674
1675 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001676 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001677 }
1678 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001679 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001680
1681 /*
1682 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1683 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001684 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1685 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001686 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001687 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001688
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001689 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001690
1691 /*
1692 * X = R^2 * R^-1 mod N = R mod N
1693 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001694 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001695 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001696
1697 if( wsize > 1 )
1698 {
1699 /*
1700 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1701 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001702 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001703
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001704 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1705 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001706
1707 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001708 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001709
Paul Bakker5121ce52009-01-03 21:22:43 +00001710 /*
1711 * W[i] = W[i - 1] * W[1]
1712 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001713 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001714 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001715 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1716 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001717
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001718 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001719 }
1720 }
1721
1722 nblimbs = E->n;
1723 bufsize = 0;
1724 nbits = 0;
1725 wbits = 0;
1726 state = 0;
1727
1728 while( 1 )
1729 {
1730 if( bufsize == 0 )
1731 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001732 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001733 break;
1734
Paul Bakker0d7702c2013-10-29 16:18:35 +01001735 nblimbs--;
1736
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001737 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001738 }
1739
1740 bufsize--;
1741
1742 ei = (E->p[nblimbs] >> bufsize) & 1;
1743
1744 /*
1745 * skip leading 0s
1746 */
1747 if( ei == 0 && state == 0 )
1748 continue;
1749
1750 if( ei == 0 && state == 1 )
1751 {
1752 /*
1753 * out of window, square X
1754 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001755 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001756 continue;
1757 }
1758
1759 /*
1760 * add ei to current window
1761 */
1762 state = 2;
1763
1764 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001765 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001766
1767 if( nbits == wsize )
1768 {
1769 /*
1770 * X = X^wsize R^-1 mod N
1771 */
1772 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001773 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001774
1775 /*
1776 * X = X * W[wbits] R^-1 mod N
1777 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001778 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001779
1780 state--;
1781 nbits = 0;
1782 wbits = 0;
1783 }
1784 }
1785
1786 /*
1787 * process the remaining bits
1788 */
1789 for( i = 0; i < nbits; i++ )
1790 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001791 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001792
1793 wbits <<= 1;
1794
Paul Bakker66d5d072014-06-17 16:39:18 +02001795 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001796 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001797 }
1798
1799 /*
1800 * X = A^E * R * R^-1 mod N = A^E mod N
1801 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001802 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001803
Hanno Beckera4af1c42017-04-18 09:07:45 +01001804 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001805 {
1806 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001807 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001808 }
1809
Paul Bakker5121ce52009-01-03 21:22:43 +00001810cleanup:
1811
Paul Bakker66d5d072014-06-17 16:39:18 +02001812 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001813 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001814
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001815 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001816
Paul Bakker75a28602014-03-31 12:08:17 +02001817 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001818 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001819
1820 return( ret );
1821}
1822
Paul Bakker5121ce52009-01-03 21:22:43 +00001823/*
1824 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1825 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001826int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001827{
Paul Bakker23986e52011-04-24 08:57:21 +00001828 int ret;
1829 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001831
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001832 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001833
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001834 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1835 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001836
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001837 lz = mbedtls_mpi_lsb( &TA );
1838 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001839
Paul Bakker66d5d072014-06-17 16:39:18 +02001840 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001841 lz = lzt;
1842
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001843 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1844 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001845
Paul Bakker5121ce52009-01-03 21:22:43 +00001846 TA.s = TB.s = 1;
1847
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001848 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001849 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001850 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1851 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001852
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001853 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001854 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001855 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1856 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001857 }
1858 else
1859 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001860 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1861 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001862 }
1863 }
1864
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001865 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1866 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001867
1868cleanup:
1869
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001870 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001871
1872 return( ret );
1873}
1874
Paul Bakker33dc46b2014-04-30 16:11:39 +02001875/*
1876 * Fill X with size bytes of random.
1877 *
1878 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001879 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001880 * deterministic, eg for tests).
1881 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001883 int (*f_rng)(void *, unsigned char *, size_t),
1884 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001885{
Paul Bakker23986e52011-04-24 08:57:21 +00001886 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001887 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001888
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001889 if( size > MBEDTLS_MPI_MAX_SIZE )
1890 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001891
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001892 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1893 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001894
1895cleanup:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -05001896 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001897 return( ret );
1898}
1899
Paul Bakker5121ce52009-01-03 21:22:43 +00001900/*
1901 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1902 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001903int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001904{
1905 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001906 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001907
Hanno Becker4bcb4912017-04-18 15:49:39 +01001908 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001909 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001910
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001911 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1912 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1913 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001914
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001915 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001916
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001917 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001918 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001919 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001920 goto cleanup;
1921 }
1922
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001923 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1924 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1925 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1926 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001927
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001928 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1929 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1930 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1931 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001932
1933 do
1934 {
1935 while( ( TU.p[0] & 1 ) == 0 )
1936 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001937 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001938
1939 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1940 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001941 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1942 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001943 }
1944
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001945 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1946 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001947 }
1948
1949 while( ( TV.p[0] & 1 ) == 0 )
1950 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001951 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001952
1953 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1954 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001955 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1956 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001957 }
1958
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1960 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001961 }
1962
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001964 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001965 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1966 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1967 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001968 }
1969 else
1970 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001971 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1972 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1973 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001974 }
1975 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001976 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001977
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001978 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1979 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001980
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001981 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1982 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001983
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001984 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001985
1986cleanup:
1987
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1989 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1990 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001991
1992 return( ret );
1993}
1994
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001995#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001996
Paul Bakker5121ce52009-01-03 21:22:43 +00001997static const int small_prime[] =
1998{
1999 3, 5, 7, 11, 13, 17, 19, 23,
2000 29, 31, 37, 41, 43, 47, 53, 59,
2001 61, 67, 71, 73, 79, 83, 89, 97,
2002 101, 103, 107, 109, 113, 127, 131, 137,
2003 139, 149, 151, 157, 163, 167, 173, 179,
2004 181, 191, 193, 197, 199, 211, 223, 227,
2005 229, 233, 239, 241, 251, 257, 263, 269,
2006 271, 277, 281, 283, 293, 307, 311, 313,
2007 317, 331, 337, 347, 349, 353, 359, 367,
2008 373, 379, 383, 389, 397, 401, 409, 419,
2009 421, 431, 433, 439, 443, 449, 457, 461,
2010 463, 467, 479, 487, 491, 499, 503, 509,
2011 521, 523, 541, 547, 557, 563, 569, 571,
2012 577, 587, 593, 599, 601, 607, 613, 617,
2013 619, 631, 641, 643, 647, 653, 659, 661,
2014 673, 677, 683, 691, 701, 709, 719, 727,
2015 733, 739, 743, 751, 757, 761, 769, 773,
2016 787, 797, 809, 811, 821, 823, 827, 829,
2017 839, 853, 857, 859, 863, 877, 881, 883,
2018 887, 907, 911, 919, 929, 937, 941, 947,
2019 953, 967, 971, 977, 983, 991, 997, -103
2020};
2021
2022/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002023 * Small divisors test (X must be positive)
2024 *
2025 * Return values:
2026 * 0: no small factor (possible prime, more tests needed)
2027 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002028 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002029 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002030 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002031static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002032{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002033 int ret = 0;
2034 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002035 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002036
Paul Bakker5121ce52009-01-03 21:22:43 +00002037 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002038 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002039
2040 for( i = 0; small_prime[i] > 0; i++ )
2041 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002042 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002043 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002044
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002045 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002046
2047 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002048 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002049 }
2050
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002051cleanup:
2052 return( ret );
2053}
2054
2055/*
2056 * Miller-Rabin pseudo-primality test (HAC 4.24)
2057 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002059 int (*f_rng)(void *, unsigned char *, size_t),
2060 void *p_rng )
2061{
Pascal Junodb99183d2015-03-11 16:49:45 +01002062 int ret, count;
2063 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002064 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002065
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002066 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2067 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002068
Paul Bakker5121ce52009-01-03 21:22:43 +00002069 /*
2070 * W = |X| - 1
2071 * R = W >> lsb( W )
2072 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002073 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2074 s = mbedtls_mpi_lsb( &W );
2075 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2076 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002077
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002078 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002079 /*
2080 * HAC, table 4.4
2081 */
2082 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2083 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2084 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2085
2086 for( i = 0; i < n; i++ )
2087 {
2088 /*
2089 * pick a random A, 1 < A < |X| - 1
2090 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002091 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002092
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002093 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00002094 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002095 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002096 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00002097 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002098 A.p[0] |= 3;
2099
Pascal Junodb99183d2015-03-11 16:49:45 +01002100 count = 0;
2101 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002102 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002103
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002104 j = mbedtls_mpi_bitlen( &A );
2105 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002106 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002107 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002108 }
2109
2110 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002111 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002112 }
2113
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002114 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2115 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002116
2117 /*
2118 * A = A^R mod |X|
2119 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002120 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002121
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002122 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2123 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002124 continue;
2125
2126 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002127 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002128 {
2129 /*
2130 * A = A * A mod |X|
2131 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002132 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2133 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002134
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002135 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002136 break;
2137
2138 j++;
2139 }
2140
2141 /*
2142 * not prime if A != |X| - 1 or A == 1
2143 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002144 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2145 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002146 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002147 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002148 break;
2149 }
2150 }
2151
2152cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002153 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2154 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002155
2156 return( ret );
2157}
2158
2159/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002160 * Pseudo-primality test: small factors, then Miller-Rabin
2161 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002162int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002163 int (*f_rng)(void *, unsigned char *, size_t),
2164 void *p_rng )
2165{
2166 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002167 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002168
2169 XX.s = 1;
2170 XX.n = X->n;
2171 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002172
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002173 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2174 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2175 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
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, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002178 return( 0 );
2179
2180 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2181 {
2182 if( ret == 1 )
2183 return( 0 );
2184
2185 return( ret );
2186 }
2187
2188 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2189}
2190
2191/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002192 * Prime number generation
2193 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002194int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002195 int (*f_rng)(void *, unsigned char *, size_t),
2196 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002197{
Paul Bakker23986e52011-04-24 08:57:21 +00002198 int ret;
2199 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002200 mbedtls_mpi_uint r;
2201 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002202
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002203 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2204 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002205
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002207
2208 n = BITS_TO_LIMBS( nbits );
2209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002210 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002211
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002212 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002213 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002214
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002215 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002216
2217 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002218
2219 if( dh_flag == 0 )
2220 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002221 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002222 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002223 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002224 goto cleanup;
2225
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002226 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002227 }
2228 }
2229 else
2230 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002231 /*
2232 * An necessary condition for Y and X = 2Y + 1 to be prime
2233 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2234 * Make sure it is satisfied, while keeping X = 3 mod 4
2235 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002236
2237 X->p[0] |= 2;
2238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002239 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002240 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002241 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002242 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002243 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002244
2245 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002246 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2247 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002248
2249 while( 1 )
2250 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002251 /*
2252 * First, check small factors for X and Y
2253 * before doing Miller-Rabin on any of them
2254 */
2255 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2256 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2257 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2258 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002259 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002260 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002261 }
2262
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002263 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002264 goto cleanup;
2265
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002266 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002267 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002268 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2269 * so up Y by 6 and X by 12.
2270 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002271 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2272 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002273 }
2274 }
2275
2276cleanup:
2277
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002278 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002279
2280 return( ret );
2281}
2282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002283#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002284
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002285#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002286
Paul Bakker23986e52011-04-24 08:57:21 +00002287#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002288
2289static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2290{
2291 { 693, 609, 21 },
2292 { 1764, 868, 28 },
2293 { 768454923, 542167814, 1 }
2294};
2295
Paul Bakker5121ce52009-01-03 21:22:43 +00002296/*
2297 * Checkup routine
2298 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002300{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002301 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002302 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002303
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002304 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2305 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002308 "EFE021C2645FD1DC586E69184AF4A31E" \
2309 "D5F53E93B5F123FA41680867BA110131" \
2310 "944FE7952E2517337780CB0DB80E61AA" \
2311 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2312
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002313 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002314 "B2E7EFD37075B9F03FF989C7C5051C20" \
2315 "34D2A323810251127E7BF8625A4F49A5" \
2316 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2317 "5B5C25763222FEFCCFC38B832366C29E" ) );
2318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002319 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002320 "0066A198186C18C10B2F5ED9B522752A" \
2321 "9830B69916E535C8F047518A889A43A5" \
2322 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002324 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002326 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002327 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2328 "9E857EA95A03512E2BAE7391688D264A" \
2329 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2330 "8001B72E848A38CAE1C65F78E56ABDEF" \
2331 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2332 "ECF677152EF804370C1A305CAF3B5BF1" \
2333 "30879B56C61DE584A0F53A2447A51E" ) );
2334
2335 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002336 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002339 {
2340 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002342
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002343 ret = 1;
2344 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002345 }
2346
2347 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002348 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002349
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002350 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002351
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002352 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002353 "256567336059E52CAE22925474705F39A94" ) );
2354
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002355 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002356 "6613F26162223DF488E9CD48CC132C7A" \
2357 "0AC93C701B001B092E4E5B9F73BCD27B" \
2358 "9EE50D0657C77F374E903CDFA4C642" ) );
2359
2360 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002361 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002362
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002363 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2364 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002365 {
2366 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002368
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002369 ret = 1;
2370 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002371 }
2372
2373 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002374 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002375
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002378 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002379 "36E139AEA55215609D2816998ED020BB" \
2380 "BD96C37890F65171D948E9BC7CBAA4D9" \
2381 "325D24D6A3C12710F10A09FA08AB87" ) );
2382
2383 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002384 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002385
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002386 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002387 {
2388 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002389 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002390
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002391 ret = 1;
2392 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002393 }
2394
2395 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002397
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002398 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002400 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002401 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2402 "C3DBA76456363A10869622EAC2DD84EC" \
2403 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2404
2405 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002406 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002408 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002409 {
2410 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002411 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002412
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002413 ret = 1;
2414 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002415 }
2416
2417 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002418 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002419
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002420 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002421 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002422
Paul Bakker66d5d072014-06-17 16:39:18 +02002423 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002424 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002425 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2426 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002427
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002428 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002429
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002430 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002431 {
2432 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002433 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002434
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002435 ret = 1;
2436 goto cleanup;
2437 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002438 }
2439
2440 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002441 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002442
Paul Bakker5121ce52009-01-03 21:22:43 +00002443cleanup:
2444
2445 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002446 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002447
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002448 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2449 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002450
2451 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002452 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002453
2454 return( ret );
2455}
2456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002457#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002459#endif /* MBEDTLS_BIGNUM_C */