blob: 51aa0b4cb29c92d5bf99ec6aa43ab8f4bede5764 [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 */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050076static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
77{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050078 mbedtls_platform_zeroize( v, ciL * n );
79}
80
Paul Bakker5121ce52009-01-03 21:22:43 +000081/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000082 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000083 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000085{
Paul Bakker6c591fa2011-05-05 11:49:20 +000086 if( X == NULL )
87 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000088
Paul Bakker6c591fa2011-05-05 11:49:20 +000089 X->s = 1;
90 X->n = 0;
91 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000092}
93
94/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000095 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000096 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020097void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000098{
Paul Bakker6c591fa2011-05-05 11:49:20 +000099 if( X == NULL )
100 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000101
Paul Bakker6c591fa2011-05-05 11:49:20 +0000102 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000103 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200104 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200105 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000106 }
107
Paul Bakker6c591fa2011-05-05 11:49:20 +0000108 X->s = 1;
109 X->n = 0;
110 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000111}
112
113/*
114 * Enlarge to the specified number of limbs
115 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000117{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200118 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200121 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000122
Paul Bakker5121ce52009-01-03 21:22:43 +0000123 if( X->n < nblimbs )
124 {
Simon Butcher29176892016-05-20 00:19:09 +0100125 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200126 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000127
Paul Bakker5121ce52009-01-03 21:22:43 +0000128 if( X->p != NULL )
129 {
130 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200131 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200132 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 }
134
135 X->n = nblimbs;
136 X->p = p;
137 }
138
139 return( 0 );
140}
141
142/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100143 * Resize down as much as possible,
144 * while keeping at least the specified number of limbs
145 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100147{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100149 size_t i;
150
151 /* Actually resize up in this case */
152 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154
155 for( i = X->n - 1; i > 0; i-- )
156 if( X->p[i] != 0 )
157 break;
158 i++;
159
160 if( i < nblimbs )
161 i = nblimbs;
162
Simon Butcher29176892016-05-20 00:19:09 +0100163 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200164 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100165
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100166 if( X->p != NULL )
167 {
168 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200169 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100171 }
172
173 X->n = i;
174 X->p = p;
175
176 return( 0 );
177}
178
179/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000180 * Copy the contents of Y into X
181 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200182int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000183{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100184 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000185 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000186
187 if( X == Y )
188 return( 0 );
189
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200190 if( Y->p == NULL )
191 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200192 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200193 return( 0 );
194 }
195
Paul Bakker5121ce52009-01-03 21:22:43 +0000196 for( i = Y->n - 1; i > 0; i-- )
197 if( Y->p[i] != 0 )
198 break;
199 i++;
200
201 X->s = Y->s;
202
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100203 if( X->n < i )
204 {
205 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
206 }
207 else
208 {
209 memset( X->p + i, 0, ( X->n - i ) * ciL );
210 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000211
Paul Bakker5121ce52009-01-03 21:22:43 +0000212 memcpy( X->p, Y->p, i * ciL );
213
214cleanup:
215
216 return( ret );
217}
218
219/*
220 * Swap the contents of X and Y
221 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000223{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200224 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000225
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200226 memcpy( &T, X, sizeof( mbedtls_mpi ) );
227 memcpy( X, Y, sizeof( mbedtls_mpi ) );
228 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000229}
230
231/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100232 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100233 * about whether the assignment was made or not.
234 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100235 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100237{
238 int ret = 0;
239 size_t i;
240
Pascal Junodb99183d2015-03-11 16:49:45 +0100241 /* make sure assign is 0 or 1 in a time-constant manner */
242 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100243
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200244 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100245
Paul Bakker66d5d072014-06-17 16:39:18 +0200246 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100247
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100248 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200249 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100250
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100251 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200252 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100253
254cleanup:
255 return( ret );
256}
257
258/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100259 * Conditionally swap X and Y, without leaking information
260 * about whether the swap was made or not.
261 * Here it is not ok to simply swap the pointers, which whould lead to
262 * different memory access patterns when X and Y are used afterwards.
263 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200264int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100265{
266 int ret, s;
267 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100269
270 if( X == Y )
271 return( 0 );
272
Pascal Junodb99183d2015-03-11 16:49:45 +0100273 /* make sure swap is 0 or 1 in a time-constant manner */
274 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100275
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200276 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
277 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100278
279 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200280 X->s = X->s * ( 1 - swap ) + Y->s * swap;
281 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100282
283
284 for( i = 0; i < X->n; i++ )
285 {
286 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200287 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
288 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100289 }
290
291cleanup:
292 return( ret );
293}
294
295/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000296 * Set value from integer
297 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200298int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000299{
300 int ret;
301
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200302 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000303 memset( X->p, 0, X->n * ciL );
304
305 X->p[0] = ( z < 0 ) ? -z : z;
306 X->s = ( z < 0 ) ? -1 : 1;
307
308cleanup:
309
310 return( ret );
311}
312
313/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000314 * Get a specific bit
315 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200316int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000317{
318 if( X->n * biL <= pos )
319 return( 0 );
320
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200321 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000322}
323
324/*
325 * Set a bit to a specific value of 0 or 1
326 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000328{
329 int ret = 0;
330 size_t off = pos / biL;
331 size_t idx = pos % biL;
332
333 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200335
Paul Bakker2f5947e2011-05-18 15:47:11 +0000336 if( X->n * biL <= pos )
337 {
338 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200339 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000342 }
343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
345 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000346
347cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200348
Paul Bakker2f5947e2011-05-18 15:47:11 +0000349 return( ret );
350}
351
352/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200353 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000354 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000356{
Paul Bakker23986e52011-04-24 08:57:21 +0000357 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000358
359 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000360 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000361 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
362 return( count );
363
364 return( 0 );
365}
366
367/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000368 * Count leading zero bits in a given integer
369 */
370static size_t mbedtls_clz( const mbedtls_mpi_uint x )
371{
372 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100373 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000374
375 for( j = 0; j < biL; j++ )
376 {
377 if( x & mask ) break;
378
379 mask >>= 1;
380 }
381
382 return j;
383}
384
385/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200386 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200388size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000389{
Paul Bakker23986e52011-04-24 08:57:21 +0000390 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000391
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200392 if( X->n == 0 )
393 return( 0 );
394
Paul Bakker5121ce52009-01-03 21:22:43 +0000395 for( i = X->n - 1; i > 0; i-- )
396 if( X->p[i] != 0 )
397 break;
398
Simon Butcher15b15d12015-11-26 19:35:03 +0000399 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000400
Paul Bakker23986e52011-04-24 08:57:21 +0000401 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000402}
403
404/*
405 * Return the total size in bytes
406 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000408{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200409 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000410}
411
412/*
413 * Convert an ASCII character to digit value
414 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000416{
417 *d = 255;
418
419 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
420 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
421 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
422
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200423 if( *d >= (mbedtls_mpi_uint) radix )
424 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000425
426 return( 0 );
427}
428
429/*
430 * Import from an ASCII string
431 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000433{
Paul Bakker23986e52011-04-24 08:57:21 +0000434 int ret;
435 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200436 mbedtls_mpi_uint d;
437 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000438
439 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200440 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000441
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000443
Paul Bakkerff60ee62010-03-16 21:09:09 +0000444 slen = strlen( s );
445
Paul Bakker5121ce52009-01-03 21:22:43 +0000446 if( radix == 16 )
447 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100448 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200449 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
450
Paul Bakkerff60ee62010-03-16 21:09:09 +0000451 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
454 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000455
Paul Bakker23986e52011-04-24 08:57:21 +0000456 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000457 {
Paul Bakker23986e52011-04-24 08:57:21 +0000458 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000459 {
460 X->s = -1;
461 break;
462 }
463
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200464 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200465 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000466 }
467 }
468 else
469 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000471
Paul Bakkerff60ee62010-03-16 21:09:09 +0000472 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000473 {
474 if( i == 0 && s[i] == '-' )
475 {
476 X->s = -1;
477 continue;
478 }
479
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200480 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
481 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000482
483 if( X->s == 1 )
484 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000486 }
487 else
488 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000490 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000491 }
492 }
493
494cleanup:
495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000497
498 return( ret );
499}
500
501/*
502 * Helper to write the digits high-order first
503 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000505{
506 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000508
509 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000511
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
513 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000514
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
516 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000517
518 if( r < 10 )
519 *(*p)++ = (char)( r + 0x30 );
520 else
521 *(*p)++ = (char)( r + 0x37 );
522
523cleanup:
524
525 return( ret );
526}
527
528/*
529 * Export into an ASCII string
530 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100531int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
532 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000533{
Paul Bakker23986e52011-04-24 08:57:21 +0000534 int ret = 0;
535 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000536 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000538
539 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200540 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000541
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200542 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000543 if( radix >= 4 ) n >>= 1;
544 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000545 /*
546 * Round up the buffer length to an even value to ensure that there is
547 * enough room for hexadecimal values that can be represented in an odd
548 * number of digits.
549 */
550 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000551
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100552 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000553 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100554 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000556 }
557
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100558 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200559 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000560
561 if( X->s == -1 )
562 *p++ = '-';
563
564 if( radix == 16 )
565 {
Paul Bakker23986e52011-04-24 08:57:21 +0000566 int c;
567 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000568
Paul Bakker23986e52011-04-24 08:57:21 +0000569 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000570 {
Paul Bakker23986e52011-04-24 08:57:21 +0000571 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000572 {
Paul Bakker23986e52011-04-24 08:57:21 +0000573 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000574
Paul Bakker6c343d72014-07-10 14:36:19 +0200575 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000576 continue;
577
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000578 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000579 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000580 k = 1;
581 }
582 }
583 }
584 else
585 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000587
588 if( T.s == -1 )
589 T.s = 1;
590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000592 }
593
594 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100595 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000596
597cleanup:
598
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000600
601 return( ret );
602}
603
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000605/*
606 * Read X from an opened file
607 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000609{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200610 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000611 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000612 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000613 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000614 * Buffer should have space for (short) label and decimal formatted MPI,
615 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000616 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000618
619 memset( s, 0, sizeof( s ) );
620 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000622
623 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000624 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200625 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000626
Hanno Beckerb2034b72017-04-26 11:46:46 +0100627 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
628 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000629
630 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100631 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000632 if( mpi_get_digit( &d, radix, *p ) != 0 )
633 break;
634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000636}
637
638/*
639 * Write X into an opened file (or stdout if fout == NULL)
640 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000642{
Paul Bakker23986e52011-04-24 08:57:21 +0000643 int ret;
644 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000645 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000646 * Buffer should have space for (short) label and decimal formatted MPI,
647 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000648 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200649 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000650
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100651 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000652
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100653 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000654
655 if( p == NULL ) p = "";
656
657 plen = strlen( p );
658 slen = strlen( s );
659 s[slen++] = '\r';
660 s[slen++] = '\n';
661
662 if( fout != NULL )
663 {
664 if( fwrite( p, 1, plen, fout ) != plen ||
665 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000667 }
668 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000670
671cleanup:
672
673 return( ret );
674}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200675#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000676
677/*
678 * Import X from unsigned binary data, big endian
679 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000681{
Paul Bakker23986e52011-04-24 08:57:21 +0000682 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100683 size_t i, j;
684 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000685
Hanno Becker073c1992017-10-17 15:17:27 +0100686 /* Ensure that target MPI has exactly the necessary number of limbs */
687 if( X->n != limbs )
688 {
689 mbedtls_mpi_free( X );
690 mbedtls_mpi_init( X );
691 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
692 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000693
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200694 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000695
Hanno Becker073c1992017-10-17 15:17:27 +0100696 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
699cleanup:
700
701 return( ret );
702}
703
704/*
705 * Export X into unsigned binary data, big endian
706 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000708{
Paul Bakker23986e52011-04-24 08:57:21 +0000709 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000710
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200711 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000712
713 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000715
716 memset( buf, 0, buflen );
717
718 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
719 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
720
721 return( 0 );
722}
723
724/*
725 * Left-shift: X <<= count
726 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200727int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000728{
Paul Bakker23986e52011-04-24 08:57:21 +0000729 int ret;
730 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000732
733 v0 = count / (biL );
734 t1 = count & (biL - 1);
735
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200736 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000737
Paul Bakkerf9688572011-05-05 10:00:45 +0000738 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000740
741 ret = 0;
742
743 /*
744 * shift by count / limb_size
745 */
746 if( v0 > 0 )
747 {
Paul Bakker23986e52011-04-24 08:57:21 +0000748 for( i = X->n; i > v0; i-- )
749 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000750
Paul Bakker23986e52011-04-24 08:57:21 +0000751 for( ; i > 0; i-- )
752 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000753 }
754
755 /*
756 * shift by count % limb_size
757 */
758 if( t1 > 0 )
759 {
760 for( i = v0; i < X->n; i++ )
761 {
762 r1 = X->p[i] >> (biL - t1);
763 X->p[i] <<= t1;
764 X->p[i] |= r0;
765 r0 = r1;
766 }
767 }
768
769cleanup:
770
771 return( ret );
772}
773
774/*
775 * Right-shift: X >>= count
776 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200777int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000778{
Paul Bakker23986e52011-04-24 08:57:21 +0000779 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200780 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000781
782 v0 = count / biL;
783 v1 = count & (biL - 1);
784
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100785 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200786 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100787
Paul Bakker5121ce52009-01-03 21:22:43 +0000788 /*
789 * shift by count / limb_size
790 */
791 if( v0 > 0 )
792 {
793 for( i = 0; i < X->n - v0; i++ )
794 X->p[i] = X->p[i + v0];
795
796 for( ; i < X->n; i++ )
797 X->p[i] = 0;
798 }
799
800 /*
801 * shift by count % limb_size
802 */
803 if( v1 > 0 )
804 {
Paul Bakker23986e52011-04-24 08:57:21 +0000805 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000806 {
Paul Bakker23986e52011-04-24 08:57:21 +0000807 r1 = X->p[i - 1] << (biL - v1);
808 X->p[i - 1] >>= v1;
809 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000810 r0 = r1;
811 }
812 }
813
814 return( 0 );
815}
816
817/*
818 * Compare unsigned values
819 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200820int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000821{
Paul Bakker23986e52011-04-24 08:57:21 +0000822 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000823
Paul Bakker23986e52011-04-24 08:57:21 +0000824 for( i = X->n; i > 0; i-- )
825 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000826 break;
827
Paul Bakker23986e52011-04-24 08:57:21 +0000828 for( j = Y->n; j > 0; j-- )
829 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000830 break;
831
Paul Bakker23986e52011-04-24 08:57:21 +0000832 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000833 return( 0 );
834
835 if( i > j ) return( 1 );
836 if( j > i ) return( -1 );
837
Paul Bakker23986e52011-04-24 08:57:21 +0000838 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000839 {
Paul Bakker23986e52011-04-24 08:57:21 +0000840 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
841 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000842 }
843
844 return( 0 );
845}
846
847/*
848 * Compare signed values
849 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200850int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000851{
Paul Bakker23986e52011-04-24 08:57:21 +0000852 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000853
Paul Bakker23986e52011-04-24 08:57:21 +0000854 for( i = X->n; i > 0; i-- )
855 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000856 break;
857
Paul Bakker23986e52011-04-24 08:57:21 +0000858 for( j = Y->n; j > 0; j-- )
859 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000860 break;
861
Paul Bakker23986e52011-04-24 08:57:21 +0000862 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000863 return( 0 );
864
865 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000866 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000867
868 if( X->s > 0 && Y->s < 0 ) return( 1 );
869 if( Y->s > 0 && X->s < 0 ) return( -1 );
870
Paul Bakker23986e52011-04-24 08:57:21 +0000871 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000872 {
Paul Bakker23986e52011-04-24 08:57:21 +0000873 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
874 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000875 }
876
877 return( 0 );
878}
879
880/*
881 * Compare signed values
882 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200883int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000884{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200885 mbedtls_mpi Y;
886 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000887
888 *p = ( z < 0 ) ? -z : z;
889 Y.s = ( z < 0 ) ? -1 : 1;
890 Y.n = 1;
891 Y.p = p;
892
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200893 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000894}
895
896/*
897 * Unsigned addition: X = |A| + |B| (HAC 14.7)
898 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200899int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000900{
Paul Bakker23986e52011-04-24 08:57:21 +0000901 int ret;
902 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100903 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000904
905 if( X == B )
906 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200907 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000908 }
909
910 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200911 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200912
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000913 /*
914 * X should always be positive as a result of unsigned additions.
915 */
916 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000917
Paul Bakker23986e52011-04-24 08:57:21 +0000918 for( j = B->n; j > 0; j-- )
919 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000920 break;
921
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200922 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000923
924 o = B->p; p = X->p; c = 0;
925
Janos Follath6c922682015-10-30 17:43:11 +0100926 /*
927 * tmp is used because it might happen that p == o
928 */
Paul Bakker23986e52011-04-24 08:57:21 +0000929 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000930 {
Janos Follath6c922682015-10-30 17:43:11 +0100931 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000932 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100933 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000934 }
935
936 while( c != 0 )
937 {
938 if( i >= X->n )
939 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200940 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000941 p = X->p + i;
942 }
943
Paul Bakker2d319fd2012-09-16 21:34:26 +0000944 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000945 }
946
947cleanup:
948
949 return( ret );
950}
951
952/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200953 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000954 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200955static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000956{
Paul Bakker23986e52011-04-24 08:57:21 +0000957 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200958 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000959
960 for( i = c = 0; i < n; i++, s++, d++ )
961 {
962 z = ( *d < c ); *d -= c;
963 c = ( *d < *s ) + z; *d -= *s;
964 }
965
966 while( c != 0 )
967 {
968 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +0200969 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000970 }
971}
972
973/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100974 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000975 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200976int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000977{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200978 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000979 int ret;
980 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000981
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200982 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
983 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000984
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200985 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000986
987 if( X == B )
988 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200989 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000990 B = &TB;
991 }
992
993 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200994 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000995
Paul Bakker1ef7a532009-06-20 10:50:55 +0000996 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100997 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000998 */
999 X->s = 1;
1000
Paul Bakker5121ce52009-01-03 21:22:43 +00001001 ret = 0;
1002
Paul Bakker23986e52011-04-24 08:57:21 +00001003 for( n = B->n; n > 0; n-- )
1004 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001005 break;
1006
Paul Bakker23986e52011-04-24 08:57:21 +00001007 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001008
1009cleanup:
1010
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001011 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001012
1013 return( ret );
1014}
1015
1016/*
1017 * Signed addition: X = A + B
1018 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001020{
1021 int ret, s = A->s;
1022
1023 if( A->s * B->s < 0 )
1024 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001025 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001026 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001027 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001028 X->s = s;
1029 }
1030 else
1031 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001032 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001033 X->s = -s;
1034 }
1035 }
1036 else
1037 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001038 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001039 X->s = s;
1040 }
1041
1042cleanup:
1043
1044 return( ret );
1045}
1046
1047/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001048 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001049 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001051{
1052 int ret, s = A->s;
1053
1054 if( A->s * B->s > 0 )
1055 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001056 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001057 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001058 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001059 X->s = s;
1060 }
1061 else
1062 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001063 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001064 X->s = -s;
1065 }
1066 }
1067 else
1068 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001069 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001070 X->s = s;
1071 }
1072
1073cleanup:
1074
1075 return( ret );
1076}
1077
1078/*
1079 * Signed addition: X = A + b
1080 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001081int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001082{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001083 mbedtls_mpi _B;
1084 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001085
1086 p[0] = ( b < 0 ) ? -b : b;
1087 _B.s = ( b < 0 ) ? -1 : 1;
1088 _B.n = 1;
1089 _B.p = p;
1090
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001091 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001092}
1093
1094/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001095 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001096 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001097int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001098{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001099 mbedtls_mpi _B;
1100 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001101
1102 p[0] = ( b < 0 ) ? -b : b;
1103 _B.s = ( b < 0 ) ? -1 : 1;
1104 _B.n = 1;
1105 _B.p = p;
1106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001107 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001108}
1109
1110/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001111 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001112 */
1113static
1114#if defined(__APPLE__) && defined(__arm__)
1115/*
1116 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1117 * appears to need this to prevent bad ARM code generation at -O3.
1118 */
1119__attribute__ ((noinline))
1120#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001121void 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 +00001122{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001123 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001124
1125#if defined(MULADDC_HUIT)
1126 for( ; i >= 8; i -= 8 )
1127 {
1128 MULADDC_INIT
1129 MULADDC_HUIT
1130 MULADDC_STOP
1131 }
1132
1133 for( ; i > 0; i-- )
1134 {
1135 MULADDC_INIT
1136 MULADDC_CORE
1137 MULADDC_STOP
1138 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001139#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001140 for( ; i >= 16; i -= 16 )
1141 {
1142 MULADDC_INIT
1143 MULADDC_CORE MULADDC_CORE
1144 MULADDC_CORE MULADDC_CORE
1145 MULADDC_CORE MULADDC_CORE
1146 MULADDC_CORE MULADDC_CORE
1147
1148 MULADDC_CORE MULADDC_CORE
1149 MULADDC_CORE MULADDC_CORE
1150 MULADDC_CORE MULADDC_CORE
1151 MULADDC_CORE MULADDC_CORE
1152 MULADDC_STOP
1153 }
1154
1155 for( ; i >= 8; i -= 8 )
1156 {
1157 MULADDC_INIT
1158 MULADDC_CORE MULADDC_CORE
1159 MULADDC_CORE MULADDC_CORE
1160
1161 MULADDC_CORE MULADDC_CORE
1162 MULADDC_CORE MULADDC_CORE
1163 MULADDC_STOP
1164 }
1165
1166 for( ; i > 0; i-- )
1167 {
1168 MULADDC_INIT
1169 MULADDC_CORE
1170 MULADDC_STOP
1171 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001172#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001173
1174 t++;
1175
1176 do {
1177 *d += c; c = ( *d < c ); d++;
1178 }
1179 while( c != 0 );
1180}
1181
1182/*
1183 * Baseline multiplication: X = A * B (HAC 14.12)
1184 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001185int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001186{
Paul Bakker23986e52011-04-24 08:57:21 +00001187 int ret;
1188 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001189 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001190
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001191 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001193 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1194 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001195
Paul Bakker23986e52011-04-24 08:57:21 +00001196 for( i = A->n; i > 0; i-- )
1197 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001198 break;
1199
Paul Bakker23986e52011-04-24 08:57:21 +00001200 for( j = B->n; j > 0; j-- )
1201 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001202 break;
1203
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001204 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1205 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001206
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001207 for( ; j > 0; j-- )
1208 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001209
1210 X->s = A->s * B->s;
1211
1212cleanup:
1213
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001214 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001215
1216 return( ret );
1217}
1218
1219/*
1220 * Baseline multiplication: X = A * b
1221 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001222int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001223{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001224 mbedtls_mpi _B;
1225 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001226
1227 _B.s = 1;
1228 _B.n = 1;
1229 _B.p = p;
1230 p[0] = b;
1231
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001232 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001233}
1234
1235/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001236 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1237 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001238 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001239static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1240 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001241{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001242#if defined(MBEDTLS_HAVE_UDBL)
1243 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001244#else
Simon Butcher9803d072016-01-03 00:24:34 +00001245 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1246 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001247 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1248 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001249 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001250#endif
1251
Simon Butcher15b15d12015-11-26 19:35:03 +00001252 /*
1253 * Check for overflow
1254 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001255 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001256 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001257 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001258
Simon Butcherf5ba0452015-12-27 23:01:55 +00001259 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001260 }
1261
1262#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001263 dividend = (mbedtls_t_udbl) u1 << biL;
1264 dividend |= (mbedtls_t_udbl) u0;
1265 quotient = dividend / d;
1266 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1267 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1268
1269 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001270 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001271
1272 return (mbedtls_mpi_uint) quotient;
1273#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001274
1275 /*
1276 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1277 * Vol. 2 - Seminumerical Algorithms, Knuth
1278 */
1279
1280 /*
1281 * Normalize the divisor, d, and dividend, u0, u1
1282 */
1283 s = mbedtls_clz( d );
1284 d = d << s;
1285
1286 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001287 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001288 u0 = u0 << s;
1289
1290 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001291 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001292
1293 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001294 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001295
1296 /*
1297 * Find the first quotient and remainder
1298 */
1299 q1 = u1 / d1;
1300 r0 = u1 - d1 * q1;
1301
1302 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1303 {
1304 q1 -= 1;
1305 r0 += d1;
1306
1307 if ( r0 >= radix ) break;
1308 }
1309
Simon Butcherf5ba0452015-12-27 23:01:55 +00001310 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001311 q0 = rAX / d1;
1312 r0 = rAX - q0 * d1;
1313
1314 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1315 {
1316 q0 -= 1;
1317 r0 += d1;
1318
1319 if ( r0 >= radix ) break;
1320 }
1321
1322 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001323 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001324
1325 quotient = q1 * radix + q0;
1326
1327 return quotient;
1328#endif
1329}
1330
1331/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001333 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001334int 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 +00001335{
Paul Bakker23986e52011-04-24 08:57:21 +00001336 int ret;
1337 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001338 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001340 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1341 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001343 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1344 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001346 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001347 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001348 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1349 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001350 return( 0 );
1351 }
1352
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001353 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1354 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001355 X.s = Y.s = 1;
1356
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001357 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1358 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1359 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1360 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001361
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001362 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001363 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001364 {
1365 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1367 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001368 }
1369 else k = 0;
1370
1371 n = X.n - 1;
1372 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001373 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001375 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001376 {
1377 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001378 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001379 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001380 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001381
1382 for( i = n; i > t ; i-- )
1383 {
1384 if( X.p[i] >= Y.p[t] )
1385 Z.p[i - t - 1] = ~0;
1386 else
1387 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001388 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1389 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001390 }
1391
1392 Z.p[i - t - 1]++;
1393 do
1394 {
1395 Z.p[i - t - 1]--;
1396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001397 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001398 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001399 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001401
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001402 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001403 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1404 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001405 T2.p[2] = X.p[i];
1406 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001407 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001409 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1410 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1411 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001413 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001414 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001415 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1416 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1417 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001418 Z.p[i - t - 1]--;
1419 }
1420 }
1421
1422 if( Q != NULL )
1423 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001424 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001425 Q->s = A->s * B->s;
1426 }
1427
1428 if( R != NULL )
1429 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001430 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001431 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001432 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001434 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001435 R->s = 1;
1436 }
1437
1438cleanup:
1439
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001440 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1441 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001442
1443 return( ret );
1444}
1445
1446/*
1447 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001448 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001449int 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 +00001450{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001451 mbedtls_mpi _B;
1452 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001453
1454 p[0] = ( b < 0 ) ? -b : b;
1455 _B.s = ( b < 0 ) ? -1 : 1;
1456 _B.n = 1;
1457 _B.p = p;
1458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001459 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001460}
1461
1462/*
1463 * Modulo: R = A mod B
1464 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001465int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001466{
1467 int ret;
1468
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001469 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1470 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001472 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001473
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001474 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1475 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001476
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001477 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1478 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001479
1480cleanup:
1481
1482 return( ret );
1483}
1484
1485/*
1486 * Modulo: r = A mod b
1487 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001488int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001489{
Paul Bakker23986e52011-04-24 08:57:21 +00001490 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001491 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001492
1493 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001494 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001495
1496 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001497 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001498
1499 /*
1500 * handle trivial cases
1501 */
1502 if( b == 1 )
1503 {
1504 *r = 0;
1505 return( 0 );
1506 }
1507
1508 if( b == 2 )
1509 {
1510 *r = A->p[0] & 1;
1511 return( 0 );
1512 }
1513
1514 /*
1515 * general case
1516 */
Paul Bakker23986e52011-04-24 08:57:21 +00001517 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001518 {
Paul Bakker23986e52011-04-24 08:57:21 +00001519 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001520 y = ( y << biH ) | ( x >> biH );
1521 z = y / b;
1522 y -= z * b;
1523
1524 x <<= biH;
1525 y = ( y << biH ) | ( x >> biH );
1526 z = y / b;
1527 y -= z * b;
1528 }
1529
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001530 /*
1531 * If A is negative, then the current y represents a negative value.
1532 * Flipping it to the positive side.
1533 */
1534 if( A->s < 0 && y != 0 )
1535 y = b - y;
1536
Paul Bakker5121ce52009-01-03 21:22:43 +00001537 *r = y;
1538
1539 return( 0 );
1540}
1541
1542/*
1543 * Fast Montgomery initialization (thanks to Tom St Denis)
1544 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001545static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001546{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001547 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001548 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001549
1550 x = m0;
1551 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001552
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001553 for( i = biL; i >= 8; i /= 2 )
1554 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001555
1556 *mm = ~x + 1;
1557}
1558
1559/*
1560 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1561 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001562static 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 +02001563 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001564{
Paul Bakker23986e52011-04-24 08:57:21 +00001565 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001566 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001567
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001568 if( T->n < N->n + 1 || T->p == NULL )
1569 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1570
Paul Bakker5121ce52009-01-03 21:22:43 +00001571 memset( T->p, 0, T->n * ciL );
1572
1573 d = T->p;
1574 n = N->n;
1575 m = ( B->n < n ) ? B->n : n;
1576
1577 for( i = 0; i < n; i++ )
1578 {
1579 /*
1580 * T = (T + u0*B + u1*N) / 2^biL
1581 */
1582 u0 = A->p[i];
1583 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1584
1585 mpi_mul_hlp( m, B->p, d, u0 );
1586 mpi_mul_hlp( n, N->p, d, u1 );
1587
1588 *d++ = u0; d[n + 1] = 0;
1589 }
1590
Paul Bakker66d5d072014-06-17 16:39:18 +02001591 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001593 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001594 mpi_sub_hlp( n, N->p, A->p );
1595 else
1596 /* prevent timing attacks */
1597 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001598
1599 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001600}
1601
1602/*
1603 * Montgomery reduction: A = A * R^-1 mod N
1604 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001605static 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 +00001606{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001607 mbedtls_mpi_uint z = 1;
1608 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001609
Paul Bakker8ddb6452013-02-27 14:56:33 +01001610 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001611 U.p = &z;
1612
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001613 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001614}
1615
1616/*
1617 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1618 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001619int 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 +00001620{
Paul Bakker23986e52011-04-24 08:57:21 +00001621 int ret;
1622 size_t wbits, wsize, one = 1;
1623 size_t i, j, nblimbs;
1624 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001625 mbedtls_mpi_uint ei, mm, state;
1626 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001627 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001628
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001629 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001630 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001631
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001632 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1633 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001634
1635 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001636 * Init temps and window size
1637 */
1638 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001639 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1640 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001641 memset( W, 0, sizeof( W ) );
1642
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001643 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001644
1645 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1646 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1647
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001648 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1649 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001650
Paul Bakker5121ce52009-01-03 21:22:43 +00001651 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001652 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1653 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1654 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001655
1656 /*
Paul Bakker50546922012-05-19 08:40:49 +00001657 * Compensate for negative A (and correct at the end)
1658 */
1659 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001660 if( neg )
1661 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001662 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001663 Apos.s = 1;
1664 A = &Apos;
1665 }
1666
1667 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001668 * If 1st call, pre-compute R^2 mod N
1669 */
1670 if( _RR == NULL || _RR->p == NULL )
1671 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001672 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1673 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1674 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001675
1676 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001677 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001678 }
1679 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001680 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001681
1682 /*
1683 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1684 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001685 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1686 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001687 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001689
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001690 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001691
1692 /*
1693 * X = R^2 * R^-1 mod N = R mod N
1694 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001695 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001696 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001697
1698 if( wsize > 1 )
1699 {
1700 /*
1701 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1702 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001703 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001704
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001705 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1706 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001707
1708 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001709 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001710
Paul Bakker5121ce52009-01-03 21:22:43 +00001711 /*
1712 * W[i] = W[i - 1] * W[1]
1713 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001714 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001715 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001716 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1717 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001718
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001719 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001720 }
1721 }
1722
1723 nblimbs = E->n;
1724 bufsize = 0;
1725 nbits = 0;
1726 wbits = 0;
1727 state = 0;
1728
1729 while( 1 )
1730 {
1731 if( bufsize == 0 )
1732 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001733 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001734 break;
1735
Paul Bakker0d7702c2013-10-29 16:18:35 +01001736 nblimbs--;
1737
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001738 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001739 }
1740
1741 bufsize--;
1742
1743 ei = (E->p[nblimbs] >> bufsize) & 1;
1744
1745 /*
1746 * skip leading 0s
1747 */
1748 if( ei == 0 && state == 0 )
1749 continue;
1750
1751 if( ei == 0 && state == 1 )
1752 {
1753 /*
1754 * out of window, square X
1755 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001756 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001757 continue;
1758 }
1759
1760 /*
1761 * add ei to current window
1762 */
1763 state = 2;
1764
1765 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001766 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001767
1768 if( nbits == wsize )
1769 {
1770 /*
1771 * X = X^wsize R^-1 mod N
1772 */
1773 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001774 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001775
1776 /*
1777 * X = X * W[wbits] R^-1 mod N
1778 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001779 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001780
1781 state--;
1782 nbits = 0;
1783 wbits = 0;
1784 }
1785 }
1786
1787 /*
1788 * process the remaining bits
1789 */
1790 for( i = 0; i < nbits; i++ )
1791 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001792 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001793
1794 wbits <<= 1;
1795
Paul Bakker66d5d072014-06-17 16:39:18 +02001796 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001797 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001798 }
1799
1800 /*
1801 * X = A^E * R * R^-1 mod N = A^E mod N
1802 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001803 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001804
Hanno Beckera4af1c42017-04-18 09:07:45 +01001805 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001806 {
1807 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001808 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001809 }
1810
Paul Bakker5121ce52009-01-03 21:22:43 +00001811cleanup:
1812
Paul Bakker66d5d072014-06-17 16:39:18 +02001813 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001814 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001815
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001817
Paul Bakker75a28602014-03-31 12:08:17 +02001818 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001819 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001820
1821 return( ret );
1822}
1823
Paul Bakker5121ce52009-01-03 21:22:43 +00001824/*
1825 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1826 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001827int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001828{
Paul Bakker23986e52011-04-24 08:57:21 +00001829 int ret;
1830 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001831 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001832
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001833 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001834
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001835 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1836 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001837
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001838 lz = mbedtls_mpi_lsb( &TA );
1839 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001840
Paul Bakker66d5d072014-06-17 16:39:18 +02001841 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001842 lz = lzt;
1843
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1845 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001846
Paul Bakker5121ce52009-01-03 21:22:43 +00001847 TA.s = TB.s = 1;
1848
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001849 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001850 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001851 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1852 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001853
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001854 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001855 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001856 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1857 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001858 }
1859 else
1860 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001861 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1862 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001863 }
1864 }
1865
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001866 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1867 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001868
1869cleanup:
1870
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001871 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001872
1873 return( ret );
1874}
1875
Paul Bakker33dc46b2014-04-30 16:11:39 +02001876/*
1877 * Fill X with size bytes of random.
1878 *
1879 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001880 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001881 * deterministic, eg for tests).
1882 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001883int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001884 int (*f_rng)(void *, unsigned char *, size_t),
1885 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001886{
Paul Bakker23986e52011-04-24 08:57:21 +00001887 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001888 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001889
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001890 if( size > MBEDTLS_MPI_MAX_SIZE )
1891 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001892
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001893 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1894 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001895
1896cleanup:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -05001897 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001898 return( ret );
1899}
1900
Paul Bakker5121ce52009-01-03 21:22:43 +00001901/*
1902 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1903 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001904int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001905{
1906 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001907 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001908
Hanno Becker4bcb4912017-04-18 15:49:39 +01001909 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001910 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001911
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001912 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1913 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1914 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001915
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001916 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001917
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001918 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001919 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001920 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001921 goto cleanup;
1922 }
1923
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001924 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1925 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1926 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1927 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001928
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1930 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1931 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1932 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001933
1934 do
1935 {
1936 while( ( TU.p[0] & 1 ) == 0 )
1937 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001938 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001939
1940 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1941 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001942 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1943 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001944 }
1945
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001946 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1947 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001948 }
1949
1950 while( ( TV.p[0] & 1 ) == 0 )
1951 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001952 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001953
1954 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1955 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001956 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1957 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001958 }
1959
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001960 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1961 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001962 }
1963
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001964 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001965 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001966 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1967 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1968 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001969 }
1970 else
1971 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001972 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1973 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1974 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001975 }
1976 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001977 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001978
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001979 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1980 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001981
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001982 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1983 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001984
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001985 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001986
1987cleanup:
1988
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001989 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1990 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1991 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001992
1993 return( ret );
1994}
1995
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001996#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001997
Paul Bakker5121ce52009-01-03 21:22:43 +00001998static const int small_prime[] =
1999{
2000 3, 5, 7, 11, 13, 17, 19, 23,
2001 29, 31, 37, 41, 43, 47, 53, 59,
2002 61, 67, 71, 73, 79, 83, 89, 97,
2003 101, 103, 107, 109, 113, 127, 131, 137,
2004 139, 149, 151, 157, 163, 167, 173, 179,
2005 181, 191, 193, 197, 199, 211, 223, 227,
2006 229, 233, 239, 241, 251, 257, 263, 269,
2007 271, 277, 281, 283, 293, 307, 311, 313,
2008 317, 331, 337, 347, 349, 353, 359, 367,
2009 373, 379, 383, 389, 397, 401, 409, 419,
2010 421, 431, 433, 439, 443, 449, 457, 461,
2011 463, 467, 479, 487, 491, 499, 503, 509,
2012 521, 523, 541, 547, 557, 563, 569, 571,
2013 577, 587, 593, 599, 601, 607, 613, 617,
2014 619, 631, 641, 643, 647, 653, 659, 661,
2015 673, 677, 683, 691, 701, 709, 719, 727,
2016 733, 739, 743, 751, 757, 761, 769, 773,
2017 787, 797, 809, 811, 821, 823, 827, 829,
2018 839, 853, 857, 859, 863, 877, 881, 883,
2019 887, 907, 911, 919, 929, 937, 941, 947,
2020 953, 967, 971, 977, 983, 991, 997, -103
2021};
2022
2023/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002024 * Small divisors test (X must be positive)
2025 *
2026 * Return values:
2027 * 0: no small factor (possible prime, more tests needed)
2028 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002030 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002031 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002032static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002033{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002034 int ret = 0;
2035 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002036 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002037
Paul Bakker5121ce52009-01-03 21:22:43 +00002038 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002039 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002040
2041 for( i = 0; small_prime[i] > 0; i++ )
2042 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002043 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002044 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002045
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002047
2048 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002050 }
2051
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002052cleanup:
2053 return( ret );
2054}
2055
2056/*
2057 * Miller-Rabin pseudo-primality test (HAC 4.24)
2058 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002059static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002060 int (*f_rng)(void *, unsigned char *, size_t),
2061 void *p_rng )
2062{
Pascal Junodb99183d2015-03-11 16:49:45 +01002063 int ret, count;
2064 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002065 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002066
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002067 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2068 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002069
Paul Bakker5121ce52009-01-03 21:22:43 +00002070 /*
2071 * W = |X| - 1
2072 * R = W >> lsb( W )
2073 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002074 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2075 s = mbedtls_mpi_lsb( &W );
2076 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2077 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002078
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002079 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002080 /*
2081 * HAC, table 4.4
2082 */
2083 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2084 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2085 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2086
2087 for( i = 0; i < n; i++ )
2088 {
2089 /*
2090 * pick a random A, 1 < A < |X| - 1
2091 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002092 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002093
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002094 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00002095 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002096 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002097 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00002098 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002099 A.p[0] |= 3;
2100
Pascal Junodb99183d2015-03-11 16:49:45 +01002101 count = 0;
2102 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002103 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002104
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002105 j = mbedtls_mpi_bitlen( &A );
2106 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002107 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002108 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002109 }
2110
2111 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002112 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002113 }
2114
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002115 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2116 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002117
2118 /*
2119 * A = A^R mod |X|
2120 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002121 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002123 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2124 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002125 continue;
2126
2127 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002128 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002129 {
2130 /*
2131 * A = A * A mod |X|
2132 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002133 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2134 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002135
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002136 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002137 break;
2138
2139 j++;
2140 }
2141
2142 /*
2143 * not prime if A != |X| - 1 or A == 1
2144 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2146 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002147 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002148 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002149 break;
2150 }
2151 }
2152
2153cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002154 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2155 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002156
2157 return( ret );
2158}
2159
2160/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002161 * Pseudo-primality test: small factors, then Miller-Rabin
2162 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002163int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002164 int (*f_rng)(void *, unsigned char *, size_t),
2165 void *p_rng )
2166{
2167 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002168 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002169
2170 XX.s = 1;
2171 XX.n = X->n;
2172 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002173
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002174 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2175 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2176 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002177
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002178 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002179 return( 0 );
2180
2181 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2182 {
2183 if( ret == 1 )
2184 return( 0 );
2185
2186 return( ret );
2187 }
2188
2189 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2190}
2191
2192/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002193 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002194 *
Janos Follath7c025a92018-08-14 11:08:41 +01002195 * If flags is 0 and nbits is at least 1024, then the procedure
Jethro Beekman66689272018-02-14 19:24:10 -08002196 * follows the RSA probably-prime generation method of FIPS 186-4.
2197 * NB. FIPS 186-4 only allows the specific bit lengths of 1024 and 1536.
Paul Bakker5121ce52009-01-03 21:22:43 +00002198 */
Janos Follath7c025a92018-08-14 11:08:41 +01002199int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002200 int (*f_rng)(void *, unsigned char *, size_t),
2201 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002202{
Jethro Beekman66689272018-02-14 19:24:10 -08002203#ifdef MBEDTLS_HAVE_INT64
2204// ceil(2^63.5)
2205#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2206#else
2207// ceil(2^31.5)
2208#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2209#endif
2210 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002211 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002212 mbedtls_mpi_uint r;
2213 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002215 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2216 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002218 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002219
2220 n = BITS_TO_LIMBS( nbits );
2221
Jethro Beekman66689272018-02-14 19:24:10 -08002222 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002223 {
Jethro Beekman66689272018-02-14 19:24:10 -08002224 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2225 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2226 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2227
2228 k = n * biL;
2229 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2230 X->p[0] |= 1;
2231
Janos Follath7c025a92018-08-14 11:08:41 +01002232 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002233 {
Jethro Beekman66689272018-02-14 19:24:10 -08002234 ret = mbedtls_mpi_is_prime( X, f_rng, p_rng );
2235
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002236 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002237 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002238 }
Jethro Beekman66689272018-02-14 19:24:10 -08002239 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002240 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002241 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002242 * An necessary condition for Y and X = 2Y + 1 to be prime
2243 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2244 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002245 */
Jethro Beekman66689272018-02-14 19:24:10 -08002246
2247 X->p[0] |= 2;
2248
2249 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2250 if( r == 0 )
2251 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2252 else if( r == 1 )
2253 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2254
2255 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2256 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2257 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2258
2259 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002260 {
Jethro Beekman66689272018-02-14 19:24:10 -08002261 /*
2262 * First, check small factors for X and Y
2263 * before doing Miller-Rabin on any of them
2264 */
2265 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2266 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2267 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2268 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
2269 goto cleanup;
2270
2271 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2272 goto cleanup;
2273
2274 /*
2275 * Next candidates. We want to preserve Y = (X-1) / 2 and
2276 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2277 * so up Y by 6 and X by 12.
2278 */
2279 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2280 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002281 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002282 }
2283 }
2284
2285cleanup:
2286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002287 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002288
2289 return( ret );
2290}
2291
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002292#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002294#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002295
Paul Bakker23986e52011-04-24 08:57:21 +00002296#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002297
2298static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2299{
2300 { 693, 609, 21 },
2301 { 1764, 868, 28 },
2302 { 768454923, 542167814, 1 }
2303};
2304
Paul Bakker5121ce52009-01-03 21:22:43 +00002305/*
2306 * Checkup routine
2307 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002308int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002309{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002310 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002311 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002312
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002313 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2314 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002315
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002316 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002317 "EFE021C2645FD1DC586E69184AF4A31E" \
2318 "D5F53E93B5F123FA41680867BA110131" \
2319 "944FE7952E2517337780CB0DB80E61AA" \
2320 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2321
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002322 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002323 "B2E7EFD37075B9F03FF989C7C5051C20" \
2324 "34D2A323810251127E7BF8625A4F49A5" \
2325 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2326 "5B5C25763222FEFCCFC38B832366C29E" ) );
2327
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002328 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002329 "0066A198186C18C10B2F5ED9B522752A" \
2330 "9830B69916E535C8F047518A889A43A5" \
2331 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002333 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002336 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2337 "9E857EA95A03512E2BAE7391688D264A" \
2338 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2339 "8001B72E848A38CAE1C65F78E56ABDEF" \
2340 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2341 "ECF677152EF804370C1A305CAF3B5BF1" \
2342 "30879B56C61DE584A0F53A2447A51E" ) );
2343
2344 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002345 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002348 {
2349 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002350 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002351
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002352 ret = 1;
2353 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002354 }
2355
2356 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002357 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002358
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002361 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002362 "256567336059E52CAE22925474705F39A94" ) );
2363
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002364 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002365 "6613F26162223DF488E9CD48CC132C7A" \
2366 "0AC93C701B001B092E4E5B9F73BCD27B" \
2367 "9EE50D0657C77F374E903CDFA4C642" ) );
2368
2369 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002370 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002371
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002372 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2373 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002374 {
2375 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002377
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002378 ret = 1;
2379 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002380 }
2381
2382 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002386
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002387 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002388 "36E139AEA55215609D2816998ED020BB" \
2389 "BD96C37890F65171D948E9BC7CBAA4D9" \
2390 "325D24D6A3C12710F10A09FA08AB87" ) );
2391
2392 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002393 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002394
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002395 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002396 {
2397 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002398 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002399
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002400 ret = 1;
2401 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002402 }
2403
2404 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002405 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002406
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002407 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002409 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002410 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2411 "C3DBA76456363A10869622EAC2DD84EC" \
2412 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2413
2414 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002415 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002416
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002417 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002418 {
2419 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002420 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002421
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002422 ret = 1;
2423 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002424 }
2425
2426 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002427 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002428
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002429 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002430 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002431
Paul Bakker66d5d072014-06-17 16:39:18 +02002432 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002433 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2435 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002436
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002437 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002438
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002439 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002440 {
2441 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002442 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002443
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002444 ret = 1;
2445 goto cleanup;
2446 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002447 }
2448
2449 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002450 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002451
Paul Bakker5121ce52009-01-03 21:22:43 +00002452cleanup:
2453
2454 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002455 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002457 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2458 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002459
2460 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002461 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002462
2463 return( ret );
2464}
2465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002466#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002468#endif /* MBEDTLS_BIGNUM_C */