blob: bd8280b6f1501f292ed4e877dc13e1186f50e327 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000048
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <string.h>
50
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000052#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020053#else
Rich Evans00ab4702015-02-06 13:43:58 +000054#include <stdio.h>
55#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020057#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020059#endif
60
Paul Bakker34617722014-06-13 17:20:13 +020061/* Implementation that should never be optimized out by the compiler */
Alexey Skalozube17a8da2016-01-13 17:19:33 +020062static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) {
Alexey Skalozub3d53f412016-01-13 16:53:40 +020063 volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0;
Paul Bakker34617722014-06-13 17:20:13 +020064}
65
Andres Amaya Garcia7351e122017-06-26 11:20:02 +010066static void mbedtls_zeroize( void *v, size_t n ) {
67 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
68}
69
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020070#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000071#define biL (ciL << 3) /* bits in limb */
72#define biH (ciL << 2) /* half limb size */
73
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010074#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
75
Paul Bakker5121ce52009-01-03 21:22:43 +000076/*
77 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020078 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000079 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020080#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
81#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000082
83/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000084 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000085 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020086void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000087{
Paul Bakker6c591fa2011-05-05 11:49:20 +000088 if( X == NULL )
89 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000090
Paul Bakker6c591fa2011-05-05 11:49:20 +000091 X->s = 1;
92 X->n = 0;
93 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000094}
95
96/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000097 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000098 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020099void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000100{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000101 if( X == NULL )
102 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000103
Paul Bakker6c591fa2011-05-05 11:49:20 +0000104 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000105 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200106 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200107 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000108 }
109
Paul Bakker6c591fa2011-05-05 11:49:20 +0000110 X->s = 1;
111 X->n = 0;
112 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000113}
114
115/*
116 * Enlarge to the specified number of limbs
117 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200118int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000119{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000121
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200123 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000124
Paul Bakker5121ce52009-01-03 21:22:43 +0000125 if( X->n < nblimbs )
126 {
Simon Butcher29176892016-05-20 00:19:09 +0100127 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200128 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000129
Paul Bakker5121ce52009-01-03 21:22:43 +0000130 if( X->p != NULL )
131 {
132 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200133 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000135 }
136
137 X->n = nblimbs;
138 X->p = p;
139 }
140
141 return( 0 );
142}
143
144/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100145 * Resize down as much as possible,
146 * while keeping at least the specified number of limbs
147 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100149{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100151 size_t i;
152
153 /* Actually resize up in this case */
154 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200155 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100156
157 for( i = X->n - 1; i > 0; i-- )
158 if( X->p[i] != 0 )
159 break;
160 i++;
161
162 if( i < nblimbs )
163 i = nblimbs;
164
Simon Butcher29176892016-05-20 00:19:09 +0100165 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200166 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100167
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100168 if( X->p != NULL )
169 {
170 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200171 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100173 }
174
175 X->n = i;
176 X->p = p;
177
178 return( 0 );
179}
180
181/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000182 * Copy the contents of Y into X
183 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000185{
Paul Bakker23986e52011-04-24 08:57:21 +0000186 int ret;
187 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000188
189 if( X == Y )
190 return( 0 );
191
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200192 if( Y->p == NULL )
193 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200194 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200195 return( 0 );
196 }
197
Paul Bakker5121ce52009-01-03 21:22:43 +0000198 for( i = Y->n - 1; i > 0; i-- )
199 if( Y->p[i] != 0 )
200 break;
201 i++;
202
203 X->s = Y->s;
204
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000206
207 memset( X->p, 0, X->n * ciL );
208 memcpy( X->p, Y->p, i * ciL );
209
210cleanup:
211
212 return( ret );
213}
214
215/*
216 * Swap the contents of X and Y
217 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000219{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222 memcpy( &T, X, sizeof( mbedtls_mpi ) );
223 memcpy( X, Y, sizeof( mbedtls_mpi ) );
224 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000225}
226
227/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100228 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100229 * about whether the assignment was made or not.
230 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100231 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200232int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100233{
234 int ret = 0;
235 size_t i;
236
Pascal Junodb99183d2015-03-11 16:49:45 +0100237 /* make sure assign is 0 or 1 in a time-constant manner */
238 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100239
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200240 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100241
Paul Bakker66d5d072014-06-17 16:39:18 +0200242 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100243
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100244 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200245 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100246
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100247 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200248 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100249
250cleanup:
251 return( ret );
252}
253
254/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100255 * Conditionally swap X and Y, without leaking information
256 * about whether the swap was made or not.
257 * Here it is not ok to simply swap the pointers, which whould lead to
258 * different memory access patterns when X and Y are used afterwards.
259 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100261{
262 int ret, s;
263 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200264 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100265
266 if( X == Y )
267 return( 0 );
268
Pascal Junodb99183d2015-03-11 16:49:45 +0100269 /* make sure swap is 0 or 1 in a time-constant manner */
270 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100271
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200272 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
273 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274
275 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200276 X->s = X->s * ( 1 - swap ) + Y->s * swap;
277 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100278
279
280 for( i = 0; i < X->n; i++ )
281 {
282 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200283 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
284 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100285 }
286
287cleanup:
288 return( ret );
289}
290
291/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000292 * Set value from integer
293 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000295{
296 int ret;
297
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200298 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000299 memset( X->p, 0, X->n * ciL );
300
301 X->p[0] = ( z < 0 ) ? -z : z;
302 X->s = ( z < 0 ) ? -1 : 1;
303
304cleanup:
305
306 return( ret );
307}
308
309/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000310 * Get a specific bit
311 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200312int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000313{
314 if( X->n * biL <= pos )
315 return( 0 );
316
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200317 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000318}
319
320/*
321 * Set a bit to a specific value of 0 or 1
322 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200323int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000324{
325 int ret = 0;
326 size_t off = pos / biL;
327 size_t idx = pos % biL;
328
329 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200330 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200331
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332 if( X->n * biL <= pos )
333 {
334 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200335 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000336
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200337 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338 }
339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200340 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
341 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000342
343cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200344
Paul Bakker2f5947e2011-05-18 15:47:11 +0000345 return( ret );
346}
347
348/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200349 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000352{
Paul Bakker23986e52011-04-24 08:57:21 +0000353 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000354
355 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000356 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000357 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
358 return( count );
359
360 return( 0 );
361}
362
363/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000364 * Count leading zero bits in a given integer
365 */
366static size_t mbedtls_clz( const mbedtls_mpi_uint x )
367{
368 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100369 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000370
371 for( j = 0; j < biL; j++ )
372 {
373 if( x & mask ) break;
374
375 mask >>= 1;
376 }
377
378 return j;
379}
380
381/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200382 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000383 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200384size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000385{
Paul Bakker23986e52011-04-24 08:57:21 +0000386 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000387
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200388 if( X->n == 0 )
389 return( 0 );
390
Paul Bakker5121ce52009-01-03 21:22:43 +0000391 for( i = X->n - 1; i > 0; i-- )
392 if( X->p[i] != 0 )
393 break;
394
Simon Butcher15b15d12015-11-26 19:35:03 +0000395 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000396
Paul Bakker23986e52011-04-24 08:57:21 +0000397 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000398}
399
400/*
401 * Return the total size in bytes
402 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200403size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000404{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200405 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000406}
407
408/*
409 * Convert an ASCII character to digit value
410 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200411static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000412{
413 *d = 255;
414
415 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
416 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
417 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
418
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419 if( *d >= (mbedtls_mpi_uint) radix )
420 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000421
422 return( 0 );
423}
424
425/*
426 * Import from an ASCII string
427 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000429{
Paul Bakker23986e52011-04-24 08:57:21 +0000430 int ret;
431 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 mbedtls_mpi_uint d;
433 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000434
435 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200436 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000437
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200438 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000439
Paul Bakkerff60ee62010-03-16 21:09:09 +0000440 slen = strlen( s );
441
Paul Bakker5121ce52009-01-03 21:22:43 +0000442 if( radix == 16 )
443 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100444 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200445 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
446
Paul Bakkerff60ee62010-03-16 21:09:09 +0000447 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
450 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000451
Paul Bakker23986e52011-04-24 08:57:21 +0000452 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000453 {
Paul Bakker23986e52011-04-24 08:57:21 +0000454 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000455 {
456 X->s = -1;
457 break;
458 }
459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200460 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200461 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000462 }
463 }
464 else
465 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200466 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000467
Paul Bakkerff60ee62010-03-16 21:09:09 +0000468 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000469 {
470 if( i == 0 && s[i] == '-' )
471 {
472 X->s = -1;
473 continue;
474 }
475
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
477 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000478
479 if( X->s == 1 )
480 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000482 }
483 else
484 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000486 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000487 }
488 }
489
490cleanup:
491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000493
494 return( ret );
495}
496
497/*
498 * Helper to write the digits high-order first
499 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200500static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000501{
502 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000504
505 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200506 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
509 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200511 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
512 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000513
514 if( r < 10 )
515 *(*p)++ = (char)( r + 0x30 );
516 else
517 *(*p)++ = (char)( r + 0x37 );
518
519cleanup:
520
521 return( ret );
522}
523
524/*
525 * Export into an ASCII string
526 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100527int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
528 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000529{
Paul Bakker23986e52011-04-24 08:57:21 +0000530 int ret = 0;
531 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000532 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000534
535 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000537
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200538 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000539 if( radix >= 4 ) n >>= 1;
540 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000541 /*
542 * Round up the buffer length to an even value to ensure that there is
543 * enough room for hexadecimal values that can be represented in an odd
544 * number of digits.
545 */
546 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000547
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100548 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000549 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100550 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200551 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000552 }
553
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100554 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000556
557 if( X->s == -1 )
558 *p++ = '-';
559
560 if( radix == 16 )
561 {
Paul Bakker23986e52011-04-24 08:57:21 +0000562 int c;
563 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000564
Paul Bakker23986e52011-04-24 08:57:21 +0000565 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000566 {
Paul Bakker23986e52011-04-24 08:57:21 +0000567 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000568 {
Paul Bakker23986e52011-04-24 08:57:21 +0000569 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000570
Paul Bakker6c343d72014-07-10 14:36:19 +0200571 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000572 continue;
573
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000574 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000575 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000576 k = 1;
577 }
578 }
579 }
580 else
581 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200582 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000583
584 if( T.s == -1 )
585 T.s = 1;
586
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200587 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000588 }
589
590 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100591 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000592
593cleanup:
594
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200595 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000596
597 return( ret );
598}
599
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200600#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000601/*
602 * Read X from an opened file
603 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000605{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200606 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000607 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000608 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000609 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000610 * Buffer should have space for (short) label and decimal formatted MPI,
611 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000612 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000614
615 memset( s, 0, sizeof( s ) );
616 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000618
619 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000620 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000622
Hanno Beckerb2034b72017-04-26 11:46:46 +0100623 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
624 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000625
626 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100627 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000628 if( mpi_get_digit( &d, radix, *p ) != 0 )
629 break;
630
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000632}
633
634/*
635 * Write X into an opened file (or stdout if fout == NULL)
636 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000638{
Paul Bakker23986e52011-04-24 08:57:21 +0000639 int ret;
640 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000641 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000642 * Buffer should have space for (short) label and decimal formatted MPI,
643 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000644 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200645 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000646
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100647 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000648
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100649 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000650
651 if( p == NULL ) p = "";
652
653 plen = strlen( p );
654 slen = strlen( s );
655 s[slen++] = '\r';
656 s[slen++] = '\n';
657
658 if( fout != NULL )
659 {
660 if( fwrite( p, 1, plen, fout ) != plen ||
661 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000663 }
664 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000666
667cleanup:
668
669 return( ret );
670}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000672
673/*
674 * Import X from unsigned binary data, big endian
675 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000677{
Paul Bakker23986e52011-04-24 08:57:21 +0000678 int ret;
679 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000680
681 for( n = 0; n < buflen; n++ )
682 if( buf[n] != 0 )
683 break;
684
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
686 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000687
Paul Bakker23986e52011-04-24 08:57:21 +0000688 for( i = buflen, j = 0; i > n; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000690
691cleanup:
692
693 return( ret );
694}
695
696/*
697 * Export X into unsigned binary data, big endian
698 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200699int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000700{
Paul Bakker23986e52011-04-24 08:57:21 +0000701 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000702
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000704
705 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
708 memset( buf, 0, buflen );
709
710 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
711 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
712
713 return( 0 );
714}
715
716/*
717 * Left-shift: X <<= count
718 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000720{
Paul Bakker23986e52011-04-24 08:57:21 +0000721 int ret;
722 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200723 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000724
725 v0 = count / (biL );
726 t1 = count & (biL - 1);
727
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200728 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000729
Paul Bakkerf9688572011-05-05 10:00:45 +0000730 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000732
733 ret = 0;
734
735 /*
736 * shift by count / limb_size
737 */
738 if( v0 > 0 )
739 {
Paul Bakker23986e52011-04-24 08:57:21 +0000740 for( i = X->n; i > v0; i-- )
741 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000742
Paul Bakker23986e52011-04-24 08:57:21 +0000743 for( ; i > 0; i-- )
744 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000745 }
746
747 /*
748 * shift by count % limb_size
749 */
750 if( t1 > 0 )
751 {
752 for( i = v0; i < X->n; i++ )
753 {
754 r1 = X->p[i] >> (biL - t1);
755 X->p[i] <<= t1;
756 X->p[i] |= r0;
757 r0 = r1;
758 }
759 }
760
761cleanup:
762
763 return( ret );
764}
765
766/*
767 * Right-shift: X >>= count
768 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200769int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000770{
Paul Bakker23986e52011-04-24 08:57:21 +0000771 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200772 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000773
774 v0 = count / biL;
775 v1 = count & (biL - 1);
776
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100777 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200778 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100779
Paul Bakker5121ce52009-01-03 21:22:43 +0000780 /*
781 * shift by count / limb_size
782 */
783 if( v0 > 0 )
784 {
785 for( i = 0; i < X->n - v0; i++ )
786 X->p[i] = X->p[i + v0];
787
788 for( ; i < X->n; i++ )
789 X->p[i] = 0;
790 }
791
792 /*
793 * shift by count % limb_size
794 */
795 if( v1 > 0 )
796 {
Paul Bakker23986e52011-04-24 08:57:21 +0000797 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000798 {
Paul Bakker23986e52011-04-24 08:57:21 +0000799 r1 = X->p[i - 1] << (biL - v1);
800 X->p[i - 1] >>= v1;
801 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000802 r0 = r1;
803 }
804 }
805
806 return( 0 );
807}
808
809/*
810 * Compare unsigned values
811 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200812int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000813{
Paul Bakker23986e52011-04-24 08:57:21 +0000814 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000815
Paul Bakker23986e52011-04-24 08:57:21 +0000816 for( i = X->n; i > 0; i-- )
817 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000818 break;
819
Paul Bakker23986e52011-04-24 08:57:21 +0000820 for( j = Y->n; j > 0; j-- )
821 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000822 break;
823
Paul Bakker23986e52011-04-24 08:57:21 +0000824 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000825 return( 0 );
826
827 if( i > j ) return( 1 );
828 if( j > i ) return( -1 );
829
Paul Bakker23986e52011-04-24 08:57:21 +0000830 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000831 {
Paul Bakker23986e52011-04-24 08:57:21 +0000832 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
833 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000834 }
835
836 return( 0 );
837}
838
839/*
840 * Compare signed values
841 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200842int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000843{
Paul Bakker23986e52011-04-24 08:57:21 +0000844 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000845
Paul Bakker23986e52011-04-24 08:57:21 +0000846 for( i = X->n; i > 0; i-- )
847 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000848 break;
849
Paul Bakker23986e52011-04-24 08:57:21 +0000850 for( j = Y->n; j > 0; j-- )
851 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000852 break;
853
Paul Bakker23986e52011-04-24 08:57:21 +0000854 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000855 return( 0 );
856
857 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000858 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000859
860 if( X->s > 0 && Y->s < 0 ) return( 1 );
861 if( Y->s > 0 && X->s < 0 ) return( -1 );
862
Paul Bakker23986e52011-04-24 08:57:21 +0000863 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000864 {
Paul Bakker23986e52011-04-24 08:57:21 +0000865 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
866 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000867 }
868
869 return( 0 );
870}
871
872/*
873 * Compare signed values
874 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200875int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000876{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200877 mbedtls_mpi Y;
878 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000879
880 *p = ( z < 0 ) ? -z : z;
881 Y.s = ( z < 0 ) ? -1 : 1;
882 Y.n = 1;
883 Y.p = p;
884
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200885 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000886}
887
888/*
889 * Unsigned addition: X = |A| + |B| (HAC 14.7)
890 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200891int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000892{
Paul Bakker23986e52011-04-24 08:57:21 +0000893 int ret;
894 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100895 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000896
897 if( X == B )
898 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200899 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000900 }
901
902 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200903 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200904
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000905 /*
906 * X should always be positive as a result of unsigned additions.
907 */
908 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000909
Paul Bakker23986e52011-04-24 08:57:21 +0000910 for( j = B->n; j > 0; j-- )
911 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000912 break;
913
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200914 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000915
916 o = B->p; p = X->p; c = 0;
917
Janos Follath6c922682015-10-30 17:43:11 +0100918 /*
919 * tmp is used because it might happen that p == o
920 */
Paul Bakker23986e52011-04-24 08:57:21 +0000921 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000922 {
Janos Follath6c922682015-10-30 17:43:11 +0100923 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000924 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100925 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000926 }
927
928 while( c != 0 )
929 {
930 if( i >= X->n )
931 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200932 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000933 p = X->p + i;
934 }
935
Paul Bakker2d319fd2012-09-16 21:34:26 +0000936 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000937 }
938
939cleanup:
940
941 return( ret );
942}
943
944/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200945 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000946 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000948{
Paul Bakker23986e52011-04-24 08:57:21 +0000949 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200950 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000951
952 for( i = c = 0; i < n; i++, s++, d++ )
953 {
954 z = ( *d < c ); *d -= c;
955 c = ( *d < *s ) + z; *d -= *s;
956 }
957
958 while( c != 0 )
959 {
960 z = ( *d < c ); *d -= c;
961 c = z; i++; d++;
962 }
963}
964
965/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100966 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000967 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200968int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000969{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200970 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000971 int ret;
972 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000973
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200974 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
975 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000976
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000978
979 if( X == B )
980 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200981 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000982 B = &TB;
983 }
984
985 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200986 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000987
Paul Bakker1ef7a532009-06-20 10:50:55 +0000988 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100989 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000990 */
991 X->s = 1;
992
Paul Bakker5121ce52009-01-03 21:22:43 +0000993 ret = 0;
994
Paul Bakker23986e52011-04-24 08:57:21 +0000995 for( n = B->n; n > 0; n-- )
996 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000997 break;
998
Paul Bakker23986e52011-04-24 08:57:21 +0000999 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001000
1001cleanup:
1002
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001003 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001004
1005 return( ret );
1006}
1007
1008/*
1009 * Signed addition: X = A + B
1010 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001011int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001012{
1013 int ret, s = A->s;
1014
1015 if( A->s * B->s < 0 )
1016 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001017 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001018 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001020 X->s = s;
1021 }
1022 else
1023 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001024 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001025 X->s = -s;
1026 }
1027 }
1028 else
1029 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001030 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001031 X->s = s;
1032 }
1033
1034cleanup:
1035
1036 return( ret );
1037}
1038
1039/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001040 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001041 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001043{
1044 int ret, s = A->s;
1045
1046 if( A->s * B->s > 0 )
1047 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001048 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001049 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001051 X->s = s;
1052 }
1053 else
1054 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001055 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001056 X->s = -s;
1057 }
1058 }
1059 else
1060 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001061 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001062 X->s = s;
1063 }
1064
1065cleanup:
1066
1067 return( ret );
1068}
1069
1070/*
1071 * Signed addition: X = A + b
1072 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001073int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001074{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001075 mbedtls_mpi _B;
1076 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001077
1078 p[0] = ( b < 0 ) ? -b : b;
1079 _B.s = ( b < 0 ) ? -1 : 1;
1080 _B.n = 1;
1081 _B.p = p;
1082
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001083 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001084}
1085
1086/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001087 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001088 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001089int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001090{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001091 mbedtls_mpi _B;
1092 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001093
1094 p[0] = ( b < 0 ) ? -b : b;
1095 _B.s = ( b < 0 ) ? -1 : 1;
1096 _B.n = 1;
1097 _B.p = p;
1098
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001099 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001100}
1101
1102/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001103 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001104 */
1105static
1106#if defined(__APPLE__) && defined(__arm__)
1107/*
1108 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1109 * appears to need this to prevent bad ARM code generation at -O3.
1110 */
1111__attribute__ ((noinline))
1112#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001113void 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 +00001114{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001116
1117#if defined(MULADDC_HUIT)
1118 for( ; i >= 8; i -= 8 )
1119 {
1120 MULADDC_INIT
1121 MULADDC_HUIT
1122 MULADDC_STOP
1123 }
1124
1125 for( ; i > 0; i-- )
1126 {
1127 MULADDC_INIT
1128 MULADDC_CORE
1129 MULADDC_STOP
1130 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001131#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001132 for( ; i >= 16; i -= 16 )
1133 {
1134 MULADDC_INIT
1135 MULADDC_CORE MULADDC_CORE
1136 MULADDC_CORE MULADDC_CORE
1137 MULADDC_CORE MULADDC_CORE
1138 MULADDC_CORE MULADDC_CORE
1139
1140 MULADDC_CORE MULADDC_CORE
1141 MULADDC_CORE MULADDC_CORE
1142 MULADDC_CORE MULADDC_CORE
1143 MULADDC_CORE MULADDC_CORE
1144 MULADDC_STOP
1145 }
1146
1147 for( ; i >= 8; i -= 8 )
1148 {
1149 MULADDC_INIT
1150 MULADDC_CORE MULADDC_CORE
1151 MULADDC_CORE MULADDC_CORE
1152
1153 MULADDC_CORE MULADDC_CORE
1154 MULADDC_CORE MULADDC_CORE
1155 MULADDC_STOP
1156 }
1157
1158 for( ; i > 0; i-- )
1159 {
1160 MULADDC_INIT
1161 MULADDC_CORE
1162 MULADDC_STOP
1163 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001164#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001165
1166 t++;
1167
1168 do {
1169 *d += c; c = ( *d < c ); d++;
1170 }
1171 while( c != 0 );
1172}
1173
1174/*
1175 * Baseline multiplication: X = A * B (HAC 14.12)
1176 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001177int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001178{
Paul Bakker23986e52011-04-24 08:57:21 +00001179 int ret;
1180 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001181 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001182
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001183 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001185 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1186 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001187
Paul Bakker23986e52011-04-24 08:57:21 +00001188 for( i = A->n; i > 0; i-- )
1189 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001190 break;
1191
Paul Bakker23986e52011-04-24 08:57:21 +00001192 for( j = B->n; j > 0; j-- )
1193 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001194 break;
1195
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001196 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1197 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001198
Paul Bakker23986e52011-04-24 08:57:21 +00001199 for( i++; j > 0; j-- )
1200 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001201
1202 X->s = A->s * B->s;
1203
1204cleanup:
1205
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001206 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001207
1208 return( ret );
1209}
1210
1211/*
1212 * Baseline multiplication: X = A * b
1213 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001214int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001215{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001216 mbedtls_mpi _B;
1217 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001218
1219 _B.s = 1;
1220 _B.n = 1;
1221 _B.p = p;
1222 p[0] = b;
1223
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001224 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001225}
1226
1227/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001228 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1229 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001230 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001231static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1232 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001233{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001234#if defined(MBEDTLS_HAVE_UDBL)
1235 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001236#else
Simon Butcher9803d072016-01-03 00:24:34 +00001237 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1238 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001239 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1240 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001241 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001242#endif
1243
Simon Butcher15b15d12015-11-26 19:35:03 +00001244 /*
1245 * Check for overflow
1246 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001247 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001248 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001249 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001250
Simon Butcherf5ba0452015-12-27 23:01:55 +00001251 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001252 }
1253
1254#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001255 dividend = (mbedtls_t_udbl) u1 << biL;
1256 dividend |= (mbedtls_t_udbl) u0;
1257 quotient = dividend / d;
1258 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1259 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1260
1261 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001262 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001263
1264 return (mbedtls_mpi_uint) quotient;
1265#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001266
1267 /*
1268 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1269 * Vol. 2 - Seminumerical Algorithms, Knuth
1270 */
1271
1272 /*
1273 * Normalize the divisor, d, and dividend, u0, u1
1274 */
1275 s = mbedtls_clz( d );
1276 d = d << s;
1277
1278 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001279 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001280 u0 = u0 << s;
1281
1282 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001283 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001284
1285 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001286 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001287
1288 /*
1289 * Find the first quotient and remainder
1290 */
1291 q1 = u1 / d1;
1292 r0 = u1 - d1 * q1;
1293
1294 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1295 {
1296 q1 -= 1;
1297 r0 += d1;
1298
1299 if ( r0 >= radix ) break;
1300 }
1301
Simon Butcherf5ba0452015-12-27 23:01:55 +00001302 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001303 q0 = rAX / d1;
1304 r0 = rAX - q0 * d1;
1305
1306 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1307 {
1308 q0 -= 1;
1309 r0 += d1;
1310
1311 if ( r0 >= radix ) break;
1312 }
1313
1314 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001315 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001316
1317 quotient = q1 * radix + q0;
1318
1319 return quotient;
1320#endif
1321}
1322
1323/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001324 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001325 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001326int 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 +00001327{
Paul Bakker23986e52011-04-24 08:57:21 +00001328 int ret;
1329 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001330 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1333 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001335 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1336 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001338 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001339 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001340 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1341 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001342 return( 0 );
1343 }
1344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001345 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1346 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001347 X.s = Y.s = 1;
1348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001349 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1350 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1351 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1352 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001353
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001354 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001355 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001356 {
1357 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001358 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1359 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001360 }
1361 else k = 0;
1362
1363 n = X.n - 1;
1364 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001366
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001367 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001368 {
1369 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001370 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001371 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001373
1374 for( i = n; i > t ; i-- )
1375 {
1376 if( X.p[i] >= Y.p[t] )
1377 Z.p[i - t - 1] = ~0;
1378 else
1379 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001380 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1381 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001382 }
1383
1384 Z.p[i - t - 1]++;
1385 do
1386 {
1387 Z.p[i - t - 1]--;
1388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001389 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001390 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001391 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001393
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001394 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001395 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1396 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001397 T2.p[2] = X.p[i];
1398 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001400
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001401 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1402 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1403 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001404
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001405 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001406 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001407 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1408 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1409 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001410 Z.p[i - t - 1]--;
1411 }
1412 }
1413
1414 if( Q != NULL )
1415 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001416 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001417 Q->s = A->s * B->s;
1418 }
1419
1420 if( R != NULL )
1421 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001422 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001423 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001424 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001425
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001426 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001427 R->s = 1;
1428 }
1429
1430cleanup:
1431
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001432 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1433 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001434
1435 return( ret );
1436}
1437
1438/*
1439 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001440 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001441int 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 +00001442{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001443 mbedtls_mpi _B;
1444 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001445
1446 p[0] = ( b < 0 ) ? -b : b;
1447 _B.s = ( b < 0 ) ? -1 : 1;
1448 _B.n = 1;
1449 _B.p = p;
1450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001451 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001452}
1453
1454/*
1455 * Modulo: R = A mod B
1456 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001457int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001458{
1459 int ret;
1460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001461 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1462 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001463
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001464 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1467 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001468
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001469 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1470 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001471
1472cleanup:
1473
1474 return( ret );
1475}
1476
1477/*
1478 * Modulo: r = A mod b
1479 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001480int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001481{
Paul Bakker23986e52011-04-24 08:57:21 +00001482 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001483 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001484
1485 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001486 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001487
1488 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001489 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001490
1491 /*
1492 * handle trivial cases
1493 */
1494 if( b == 1 )
1495 {
1496 *r = 0;
1497 return( 0 );
1498 }
1499
1500 if( b == 2 )
1501 {
1502 *r = A->p[0] & 1;
1503 return( 0 );
1504 }
1505
1506 /*
1507 * general case
1508 */
Paul Bakker23986e52011-04-24 08:57:21 +00001509 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001510 {
Paul Bakker23986e52011-04-24 08:57:21 +00001511 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001512 y = ( y << biH ) | ( x >> biH );
1513 z = y / b;
1514 y -= z * b;
1515
1516 x <<= biH;
1517 y = ( y << biH ) | ( x >> biH );
1518 z = y / b;
1519 y -= z * b;
1520 }
1521
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001522 /*
1523 * If A is negative, then the current y represents a negative value.
1524 * Flipping it to the positive side.
1525 */
1526 if( A->s < 0 && y != 0 )
1527 y = b - y;
1528
Paul Bakker5121ce52009-01-03 21:22:43 +00001529 *r = y;
1530
1531 return( 0 );
1532}
1533
1534/*
1535 * Fast Montgomery initialization (thanks to Tom St Denis)
1536 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001537static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001538{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001540 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001541
1542 x = m0;
1543 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001544
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001545 for( i = biL; i >= 8; i /= 2 )
1546 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001547
1548 *mm = ~x + 1;
1549}
1550
1551/*
1552 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1553 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001554static 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 +02001555 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001556{
Paul Bakker23986e52011-04-24 08:57:21 +00001557 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001558 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001559
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001560 if( T->n < N->n + 1 || T->p == NULL )
1561 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1562
Paul Bakker5121ce52009-01-03 21:22:43 +00001563 memset( T->p, 0, T->n * ciL );
1564
1565 d = T->p;
1566 n = N->n;
1567 m = ( B->n < n ) ? B->n : n;
1568
1569 for( i = 0; i < n; i++ )
1570 {
1571 /*
1572 * T = (T + u0*B + u1*N) / 2^biL
1573 */
1574 u0 = A->p[i];
1575 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1576
1577 mpi_mul_hlp( m, B->p, d, u0 );
1578 mpi_mul_hlp( n, N->p, d, u1 );
1579
1580 *d++ = u0; d[n + 1] = 0;
1581 }
1582
Paul Bakker66d5d072014-06-17 16:39:18 +02001583 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001584
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001585 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001586 mpi_sub_hlp( n, N->p, A->p );
1587 else
1588 /* prevent timing attacks */
1589 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001590
1591 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001592}
1593
1594/*
1595 * Montgomery reduction: A = A * R^-1 mod N
1596 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001597static 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 +00001598{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001599 mbedtls_mpi_uint z = 1;
1600 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001601
Paul Bakker8ddb6452013-02-27 14:56:33 +01001602 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001603 U.p = &z;
1604
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001605 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001606}
1607
1608/*
1609 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1610 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001611int 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 +00001612{
Paul Bakker23986e52011-04-24 08:57:21 +00001613 int ret;
1614 size_t wbits, wsize, one = 1;
1615 size_t i, j, nblimbs;
1616 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001617 mbedtls_mpi_uint ei, mm, state;
1618 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001619 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001620
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001621 if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
1622 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001623
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001624 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1625 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001626
1627 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001628 * Init temps and window size
1629 */
1630 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001631 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1632 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001633 memset( W, 0, sizeof( W ) );
1634
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001635 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001636
1637 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1638 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1639
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001640 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1641 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001642
Paul Bakker5121ce52009-01-03 21:22:43 +00001643 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001644 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1645 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1646 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001647
1648 /*
Paul Bakker50546922012-05-19 08:40:49 +00001649 * Compensate for negative A (and correct at the end)
1650 */
1651 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001652 if( neg )
1653 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001654 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001655 Apos.s = 1;
1656 A = &Apos;
1657 }
1658
1659 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001660 * If 1st call, pre-compute R^2 mod N
1661 */
1662 if( _RR == NULL || _RR->p == NULL )
1663 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001664 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1665 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1666 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001667
1668 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001669 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001670 }
1671 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001672 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001673
1674 /*
1675 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1676 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001677 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1678 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001679 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001680 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001681
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001682 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001683
1684 /*
1685 * X = R^2 * R^-1 mod N = R mod N
1686 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001687 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001688 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001689
1690 if( wsize > 1 )
1691 {
1692 /*
1693 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1694 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001695 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001697 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1698 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001699
1700 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001701 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001702
Paul Bakker5121ce52009-01-03 21:22:43 +00001703 /*
1704 * W[i] = W[i - 1] * W[1]
1705 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001706 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001707 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001708 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1709 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001710
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001711 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001712 }
1713 }
1714
1715 nblimbs = E->n;
1716 bufsize = 0;
1717 nbits = 0;
1718 wbits = 0;
1719 state = 0;
1720
1721 while( 1 )
1722 {
1723 if( bufsize == 0 )
1724 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001725 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001726 break;
1727
Paul Bakker0d7702c2013-10-29 16:18:35 +01001728 nblimbs--;
1729
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001730 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001731 }
1732
1733 bufsize--;
1734
1735 ei = (E->p[nblimbs] >> bufsize) & 1;
1736
1737 /*
1738 * skip leading 0s
1739 */
1740 if( ei == 0 && state == 0 )
1741 continue;
1742
1743 if( ei == 0 && state == 1 )
1744 {
1745 /*
1746 * out of window, square X
1747 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001748 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001749 continue;
1750 }
1751
1752 /*
1753 * add ei to current window
1754 */
1755 state = 2;
1756
1757 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001758 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001759
1760 if( nbits == wsize )
1761 {
1762 /*
1763 * X = X^wsize R^-1 mod N
1764 */
1765 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001766 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001767
1768 /*
1769 * X = X * W[wbits] R^-1 mod N
1770 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001771 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001772
1773 state--;
1774 nbits = 0;
1775 wbits = 0;
1776 }
1777 }
1778
1779 /*
1780 * process the remaining bits
1781 */
1782 for( i = 0; i < nbits; i++ )
1783 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001784 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001785
1786 wbits <<= 1;
1787
Paul Bakker66d5d072014-06-17 16:39:18 +02001788 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001789 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001790 }
1791
1792 /*
1793 * X = A^E * R * R^-1 mod N = A^E mod N
1794 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001795 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001796
Hanno Beckera4af1c42017-04-18 09:07:45 +01001797 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001798 {
1799 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001800 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001801 }
1802
Paul Bakker5121ce52009-01-03 21:22:43 +00001803cleanup:
1804
Paul Bakker66d5d072014-06-17 16:39:18 +02001805 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001806 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001807
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001808 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001809
Paul Bakker75a28602014-03-31 12:08:17 +02001810 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001811 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001812
1813 return( ret );
1814}
1815
Paul Bakker5121ce52009-01-03 21:22:43 +00001816/*
1817 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1818 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001819int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001820{
Paul Bakker23986e52011-04-24 08:57:21 +00001821 int ret;
1822 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001823 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001824
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001825 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001826
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001827 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1828 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001829
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830 lz = mbedtls_mpi_lsb( &TA );
1831 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001832
Paul Bakker66d5d072014-06-17 16:39:18 +02001833 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001834 lz = lzt;
1835
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001836 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1837 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001838
Paul Bakker5121ce52009-01-03 21:22:43 +00001839 TA.s = TB.s = 1;
1840
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001841 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001842 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001843 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1844 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001845
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001846 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001847 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001848 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1849 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001850 }
1851 else
1852 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001853 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1854 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001855 }
1856 }
1857
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001858 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1859 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001860
1861cleanup:
1862
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001863 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001864
1865 return( ret );
1866}
1867
Paul Bakker33dc46b2014-04-30 16:11:39 +02001868/*
1869 * Fill X with size bytes of random.
1870 *
1871 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001872 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001873 * deterministic, eg for tests).
1874 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001875int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001876 int (*f_rng)(void *, unsigned char *, size_t),
1877 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001878{
Paul Bakker23986e52011-04-24 08:57:21 +00001879 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001881
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882 if( size > MBEDTLS_MPI_MAX_SIZE )
1883 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001884
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001885 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1886 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001887
1888cleanup:
Andres Amaya Garcia7351e122017-06-26 11:20:02 +01001889 mbedtls_zeroize( buf, sizeof( buf ) );
1890
Paul Bakker287781a2011-03-26 13:18:49 +00001891 return( ret );
1892}
1893
Paul Bakker5121ce52009-01-03 21:22:43 +00001894/*
1895 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1896 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001897int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001898{
1899 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001900 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001901
Hanno Becker4bcb4912017-04-18 15:49:39 +01001902 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001903 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001904
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001905 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1906 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1907 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001908
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001909 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001910
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001911 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001912 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001913 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001914 goto cleanup;
1915 }
1916
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001917 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1918 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1919 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1920 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001921
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001922 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1923 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1924 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1925 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001926
1927 do
1928 {
1929 while( ( TU.p[0] & 1 ) == 0 )
1930 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001931 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001932
1933 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1934 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001935 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1936 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001937 }
1938
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001939 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1940 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001941 }
1942
1943 while( ( TV.p[0] & 1 ) == 0 )
1944 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001945 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001946
1947 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1948 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001949 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1950 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001951 }
1952
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001953 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1954 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001955 }
1956
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001957 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001958 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1960 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1961 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001962 }
1963 else
1964 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001965 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1966 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1967 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001968 }
1969 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001970 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001971
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001972 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1973 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001974
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001975 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1976 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001977
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001978 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001979
1980cleanup:
1981
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001982 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1983 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1984 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001985
1986 return( ret );
1987}
1988
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001989#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001990
Paul Bakker5121ce52009-01-03 21:22:43 +00001991static const int small_prime[] =
1992{
1993 3, 5, 7, 11, 13, 17, 19, 23,
1994 29, 31, 37, 41, 43, 47, 53, 59,
1995 61, 67, 71, 73, 79, 83, 89, 97,
1996 101, 103, 107, 109, 113, 127, 131, 137,
1997 139, 149, 151, 157, 163, 167, 173, 179,
1998 181, 191, 193, 197, 199, 211, 223, 227,
1999 229, 233, 239, 241, 251, 257, 263, 269,
2000 271, 277, 281, 283, 293, 307, 311, 313,
2001 317, 331, 337, 347, 349, 353, 359, 367,
2002 373, 379, 383, 389, 397, 401, 409, 419,
2003 421, 431, 433, 439, 443, 449, 457, 461,
2004 463, 467, 479, 487, 491, 499, 503, 509,
2005 521, 523, 541, 547, 557, 563, 569, 571,
2006 577, 587, 593, 599, 601, 607, 613, 617,
2007 619, 631, 641, 643, 647, 653, 659, 661,
2008 673, 677, 683, 691, 701, 709, 719, 727,
2009 733, 739, 743, 751, 757, 761, 769, 773,
2010 787, 797, 809, 811, 821, 823, 827, 829,
2011 839, 853, 857, 859, 863, 877, 881, 883,
2012 887, 907, 911, 919, 929, 937, 941, 947,
2013 953, 967, 971, 977, 983, 991, 997, -103
2014};
2015
2016/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002017 * Small divisors test (X must be positive)
2018 *
2019 * Return values:
2020 * 0: no small factor (possible prime, more tests needed)
2021 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002022 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002023 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002024 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002025static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002026{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002027 int ret = 0;
2028 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002030
Paul Bakker5121ce52009-01-03 21:22:43 +00002031 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002032 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002033
2034 for( i = 0; small_prime[i] > 0; i++ )
2035 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002036 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002037 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002038
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002039 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002040
2041 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002042 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002043 }
2044
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002045cleanup:
2046 return( ret );
2047}
2048
2049/*
2050 * Miller-Rabin pseudo-primality test (HAC 4.24)
2051 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002053 int (*f_rng)(void *, unsigned char *, size_t),
2054 void *p_rng )
2055{
Pascal Junodb99183d2015-03-11 16:49:45 +01002056 int ret, count;
2057 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2061 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002062
Paul Bakker5121ce52009-01-03 21:22:43 +00002063 /*
2064 * W = |X| - 1
2065 * R = W >> lsb( W )
2066 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002067 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2068 s = mbedtls_mpi_lsb( &W );
2069 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2070 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002071
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002072 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002073 /*
2074 * HAC, table 4.4
2075 */
2076 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2077 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2078 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2079
2080 for( i = 0; i < n; i++ )
2081 {
2082 /*
2083 * pick a random A, 1 < A < |X| - 1
2084 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002085 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002086
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002087 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00002088 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002089 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002090 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00002091 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002092 A.p[0] |= 3;
2093
Pascal Junodb99183d2015-03-11 16:49:45 +01002094 count = 0;
2095 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002096 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002097
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002098 j = mbedtls_mpi_bitlen( &A );
2099 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002100 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002101 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002102 }
2103
2104 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002105 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002106 }
2107
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002108 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2109 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002110
2111 /*
2112 * A = A^R mod |X|
2113 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002114 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002115
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002116 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2117 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002118 continue;
2119
2120 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002121 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002122 {
2123 /*
2124 * A = A * A mod |X|
2125 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002126 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2127 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002129 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002130 break;
2131
2132 j++;
2133 }
2134
2135 /*
2136 * not prime if A != |X| - 1 or A == 1
2137 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002138 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2139 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002140 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002141 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002142 break;
2143 }
2144 }
2145
2146cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002147 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2148 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002149
2150 return( ret );
2151}
2152
2153/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002154 * Pseudo-primality test: small factors, then Miller-Rabin
2155 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002156int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002157 int (*f_rng)(void *, unsigned char *, size_t),
2158 void *p_rng )
2159{
2160 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002161 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002162
2163 XX.s = 1;
2164 XX.n = X->n;
2165 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002166
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002167 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2168 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2169 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002170
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002171 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002172 return( 0 );
2173
2174 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2175 {
2176 if( ret == 1 )
2177 return( 0 );
2178
2179 return( ret );
2180 }
2181
2182 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2183}
2184
2185/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002186 * Prime number generation
2187 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002189 int (*f_rng)(void *, unsigned char *, size_t),
2190 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002191{
Paul Bakker23986e52011-04-24 08:57:21 +00002192 int ret;
2193 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002194 mbedtls_mpi_uint r;
2195 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002196
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002197 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2198 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002199
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002200 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002201
2202 n = BITS_TO_LIMBS( nbits );
2203
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002204 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002205
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002206 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002207 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002208
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002209 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002210
2211 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002212
2213 if( dh_flag == 0 )
2214 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002215 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002216 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002217 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002218 goto cleanup;
2219
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002220 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002221 }
2222 }
2223 else
2224 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002225 /*
2226 * An necessary condition for Y and X = 2Y + 1 to be prime
2227 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2228 * Make sure it is satisfied, while keeping X = 3 mod 4
2229 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002230
2231 X->p[0] |= 2;
2232
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002233 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002234 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002235 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002236 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002237 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002238
2239 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002240 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2241 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002242
2243 while( 1 )
2244 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002245 /*
2246 * First, check small factors for X and Y
2247 * before doing Miller-Rabin on any of them
2248 */
2249 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2250 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2251 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2252 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002253 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002254 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002255 }
2256
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002257 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002258 goto cleanup;
2259
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002260 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002261 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002262 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2263 * so up Y by 6 and X by 12.
2264 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002265 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2266 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002267 }
2268 }
2269
2270cleanup:
2271
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002273
2274 return( ret );
2275}
2276
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002277#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002278
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002279#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002280
Paul Bakker23986e52011-04-24 08:57:21 +00002281#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002282
2283static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2284{
2285 { 693, 609, 21 },
2286 { 1764, 868, 28 },
2287 { 768454923, 542167814, 1 }
2288};
2289
Paul Bakker5121ce52009-01-03 21:22:43 +00002290/*
2291 * Checkup routine
2292 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002293int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002294{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002295 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002296 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002297
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002298 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2299 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002300
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002301 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002302 "EFE021C2645FD1DC586E69184AF4A31E" \
2303 "D5F53E93B5F123FA41680867BA110131" \
2304 "944FE7952E2517337780CB0DB80E61AA" \
2305 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002308 "B2E7EFD37075B9F03FF989C7C5051C20" \
2309 "34D2A323810251127E7BF8625A4F49A5" \
2310 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2311 "5B5C25763222FEFCCFC38B832366C29E" ) );
2312
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002313 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002314 "0066A198186C18C10B2F5ED9B522752A" \
2315 "9830B69916E535C8F047518A889A43A5" \
2316 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2317
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002318 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002320 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002321 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2322 "9E857EA95A03512E2BAE7391688D264A" \
2323 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2324 "8001B72E848A38CAE1C65F78E56ABDEF" \
2325 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2326 "ECF677152EF804370C1A305CAF3B5BF1" \
2327 "30879B56C61DE584A0F53A2447A51E" ) );
2328
2329 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002332 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002333 {
2334 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002336
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002337 ret = 1;
2338 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002339 }
2340
2341 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002344 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002346 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002347 "256567336059E52CAE22925474705F39A94" ) );
2348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002349 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002350 "6613F26162223DF488E9CD48CC132C7A" \
2351 "0AC93C701B001B092E4E5B9F73BCD27B" \
2352 "9EE50D0657C77F374E903CDFA4C642" ) );
2353
2354 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002355 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002356
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002357 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2358 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002359 {
2360 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002361 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002362
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002363 ret = 1;
2364 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002365 }
2366
2367 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002368 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002370 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002371
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002372 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002373 "36E139AEA55215609D2816998ED020BB" \
2374 "BD96C37890F65171D948E9BC7CBAA4D9" \
2375 "325D24D6A3C12710F10A09FA08AB87" ) );
2376
2377 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002378 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002379
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002380 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002381 {
2382 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002384
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002385 ret = 1;
2386 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002387 }
2388
2389 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002390 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002392 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002393
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002394 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002395 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2396 "C3DBA76456363A10869622EAC2DD84EC" \
2397 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2398
2399 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002400 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002401
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002402 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002403 {
2404 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002405 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002406
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002407 ret = 1;
2408 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002409 }
2410
2411 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002412 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002413
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002414 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002415 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002416
Paul Bakker66d5d072014-06-17 16:39:18 +02002417 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002418 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002419 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2420 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002421
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002422 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002424 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002425 {
2426 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002427 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002428
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002429 ret = 1;
2430 goto cleanup;
2431 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002432 }
2433
2434 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002435 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002436
Paul Bakker5121ce52009-01-03 21:22:43 +00002437cleanup:
2438
2439 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002441
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002442 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2443 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002444
2445 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002446 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002447
2448 return( ret );
2449}
2450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002451#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002453#endif /* MBEDTLS_BIGNUM_C */