blob: d3a150c3c1bd6d0f98a737435fb8a0a522da23d4 [file] [log] [blame] [raw]
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
Paul Bakker5121ce52009-01-03 21:22:43 +000060
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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020066#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000067#define biL (ciL << 3) /* bits in limb */
68#define biH (ciL << 2) /* half limb size */
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010069
70#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
Paul Bakker5121ce52009-01-03 21:22:43 +000071
72/*
73 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020074 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000075 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020076#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
77#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000078
79/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000080 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000081 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000083{
Paul Bakker6c591fa2011-05-05 11:49:20 +000084 if( X == NULL )
85 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000086
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 X->s = 1;
88 X->n = 0;
89 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000090}
91
92/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000094 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020095void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000096{
Paul Bakker6c591fa2011-05-05 11:49:20 +000097 if( X == NULL )
98 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000099
Paul Bakker6c591fa2011-05-05 11:49:20 +0000100 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000101 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200102 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200103 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000104 }
105
Paul Bakker6c591fa2011-05-05 11:49:20 +0000106 X->s = 1;
107 X->n = 0;
108 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000109}
110
111/*
112 * Enlarge to the specified number of limbs
113 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200114int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000115{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116 mbedtls_mpi_uint *p;
Paul Bakkerf9688572011-05-05 10:00:45 +0000117
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200118 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200119 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000120
121 if( X->n < nblimbs )
122 {
Simon Butcher29176892016-05-20 00:19:09 +0100123 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200124 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000125
126 if( X->p != NULL )
127 {
128 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200129 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000131 }
132
133 X->n = nblimbs;
134 X->p = p;
135 }
136
137 return( 0 );
138}
139
140/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100141 * Resize down as much as possible,
142 * while keeping at least the specified number of limbs
143 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100145{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100147 size_t i;
148
149 /* Actually resize up in this case */
150 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152
153 for( i = X->n - 1; i > 0; i-- )
154 if( X->p[i] != 0 )
155 break;
156 i++;
157
158 if( i < nblimbs )
159 i = nblimbs;
160
Simon Butcher29176892016-05-20 00:19:09 +0100161 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200162 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163
164 if( X->p != NULL )
165 {
166 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200167 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100169 }
170
171 X->n = i;
172 X->p = p;
173
174 return( 0 );
175}
176
177/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000178 * Copy the contents of Y into X
179 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000181{
Paul Bakker23986e52011-04-24 08:57:21 +0000182 int ret;
183 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000184
185 if( X == Y )
186 return( 0 );
187
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200188 if( Y->p == NULL )
189 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200191 return( 0 );
192 }
193
Paul Bakker5121ce52009-01-03 21:22:43 +0000194 for( i = Y->n - 1; i > 0; i-- )
195 if( Y->p[i] != 0 )
196 break;
197 i++;
198
199 X->s = Y->s;
200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200201 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000202
203 memset( X->p, 0, X->n * ciL );
204 memcpy( X->p, Y->p, i * ciL );
205
206cleanup:
207
208 return( ret );
209}
210
211/*
212 * Swap the contents of X and Y
213 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200214void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000215{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218 memcpy( &T, X, sizeof( mbedtls_mpi ) );
219 memcpy( X, Y, sizeof( mbedtls_mpi ) );
220 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000221}
222
223/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100224 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100225 * about whether the assignment was made or not.
226 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100227 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100229{
230 int ret = 0;
231 size_t i;
232
Pascal Junodb99183d2015-03-11 16:49:45 +0100233 /* make sure assign is 0 or 1 in a time-constant manner */
234 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100235
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100237
Paul Bakker66d5d072014-06-17 16:39:18 +0200238 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100239
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100240 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200241 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100242
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100243 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200244 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100245
246cleanup:
247 return( ret );
248}
249
250/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100251 * Conditionally swap X and Y, without leaking information
252 * about whether the swap was made or not.
253 * Here it is not ok to simply swap the pointers, which whould lead to
254 * different memory access patterns when X and Y are used afterwards.
255 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100257{
258 int ret, s;
259 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100261
262 if( X == Y )
263 return( 0 );
264
Pascal Junodb99183d2015-03-11 16:49:45 +0100265 /* make sure swap is 0 or 1 in a time-constant manner */
266 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
269 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100270
271 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200272 X->s = X->s * ( 1 - swap ) + Y->s * swap;
273 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274
275
276 for( i = 0; i < X->n; i++ )
277 {
278 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200279 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
280 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100281 }
282
283cleanup:
284 return( ret );
285}
286
287/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000288 * Set value from integer
289 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200290int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000291{
292 int ret;
293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000295 memset( X->p, 0, X->n * ciL );
296
297 X->p[0] = ( z < 0 ) ? -z : z;
298 X->s = ( z < 0 ) ? -1 : 1;
299
300cleanup:
301
302 return( ret );
303}
304
305/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000306 * Get a specific bit
307 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000309{
310 if( X->n * biL <= pos )
311 return( 0 );
312
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200313 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000314}
315
316/*
317 * Set a bit to a specific value of 0 or 1
318 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200319int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000320{
321 int ret = 0;
322 size_t off = pos / biL;
323 size_t idx = pos % biL;
324
325 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200327
Paul Bakker2f5947e2011-05-18 15:47:11 +0000328 if( X->n * biL <= pos )
329 {
330 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200331 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200333 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000334 }
335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
337 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338
339cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200340
Paul Bakker2f5947e2011-05-18 15:47:11 +0000341 return( ret );
342}
343
344/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200345 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000346 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000348{
Paul Bakker23986e52011-04-24 08:57:21 +0000349 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000350
351 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000352 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000353 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
354 return( count );
355
356 return( 0 );
357}
358
359/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000360 * Count leading zero bits in a given integer
361 */
362static size_t mbedtls_clz( const mbedtls_mpi_uint x )
363{
364 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100365 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000366
367 for( j = 0; j < biL; j++ )
368 {
369 if( x & mask ) break;
370
371 mask >>= 1;
372 }
373
374 return j;
375}
376
377/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200378 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200380size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000381{
Paul Bakker23986e52011-04-24 08:57:21 +0000382 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000383
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200384 if( X->n == 0 )
385 return( 0 );
386
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 for( i = X->n - 1; i > 0; i-- )
388 if( X->p[i] != 0 )
389 break;
390
Simon Butcher15b15d12015-11-26 19:35:03 +0000391 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000392
Paul Bakker23986e52011-04-24 08:57:21 +0000393 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000394}
395
396/*
397 * Return the total size in bytes
398 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000400{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200401 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000402}
403
404/*
405 * Convert an ASCII character to digit value
406 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000408{
409 *d = 255;
410
411 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
412 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
413 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
414
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415 if( *d >= (mbedtls_mpi_uint) radix )
416 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
418 return( 0 );
419}
420
421/*
422 * Import from an ASCII string
423 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000425{
Paul Bakker23986e52011-04-24 08:57:21 +0000426 int ret;
427 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 mbedtls_mpi_uint d;
429 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000430
431 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000435
Paul Bakkerff60ee62010-03-16 21:09:09 +0000436 slen = strlen( s );
437
Paul Bakker5121ce52009-01-03 21:22:43 +0000438 if( radix == 16 )
439 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100440 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200441 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
442
Paul Bakkerff60ee62010-03-16 21:09:09 +0000443 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
446 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000447
Paul Bakker23986e52011-04-24 08:57:21 +0000448 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000449 {
Paul Bakker23986e52011-04-24 08:57:21 +0000450 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000451 {
452 X->s = -1;
453 break;
454 }
455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200457 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 }
459 }
460 else
461 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000463
Paul Bakkerff60ee62010-03-16 21:09:09 +0000464 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000465 {
466 if( i == 0 && s[i] == '-' )
467 {
468 X->s = -1;
469 continue;
470 }
471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
473 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000474
475 if( X->s == 1 )
476 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000478 }
479 else
480 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000482 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000483 }
484 }
485
486cleanup:
487
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200488 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000489
490 return( ret );
491}
492
493/*
494 * Helper to write the digits high-order first
495 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000497{
498 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000500
501 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
505 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
508 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000509
510 if( r < 10 )
511 *(*p)++ = (char)( r + 0x30 );
512 else
513 *(*p)++ = (char)( r + 0x37 );
514
515cleanup:
516
517 return( ret );
518}
519
520/*
521 * Export into an ASCII string
522 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100523int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
524 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000525{
Paul Bakker23986e52011-04-24 08:57:21 +0000526 int ret = 0;
527 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000528 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000530
531 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000533
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200534 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000535 if( radix >= 4 ) n >>= 1;
536 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000537 /*
538 * Round up the buffer length to an even value to ensure that there is
539 * enough room for hexadecimal values that can be represented in an odd
540 * number of digits.
541 */
542 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000543
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100544 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000545 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100546 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200547 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000548 }
549
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100550 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200551 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000552
553 if( X->s == -1 )
554 *p++ = '-';
555
556 if( radix == 16 )
557 {
Paul Bakker23986e52011-04-24 08:57:21 +0000558 int c;
559 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000560
Paul Bakker23986e52011-04-24 08:57:21 +0000561 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000562 {
Paul Bakker23986e52011-04-24 08:57:21 +0000563 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000564 {
Paul Bakker23986e52011-04-24 08:57:21 +0000565 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000566
Paul Bakker6c343d72014-07-10 14:36:19 +0200567 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000568 continue;
569
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000570 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000571 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000572 k = 1;
573 }
574 }
575 }
576 else
577 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000579
580 if( T.s == -1 )
581 T.s = 1;
582
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200583 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000584 }
585
586 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100587 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000588
589cleanup:
590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000592
593 return( ret );
594}
595
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200596#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000597/*
598 * Read X from an opened file
599 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200600int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000601{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000603 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000604 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000605 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000606 * Buffer should have space for (short) label and decimal formatted MPI,
607 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000608 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200609 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000610
611 memset( s, 0, sizeof( s ) );
612 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000614
615 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000616 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000618
Hanno Beckerb2034b72017-04-26 11:46:46 +0100619 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
620 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000621
622 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100623 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000624 if( mpi_get_digit( &d, radix, *p ) != 0 )
625 break;
626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200627 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000628}
629
630/*
631 * Write X into an opened file (or stdout if fout == NULL)
632 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200633int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000634{
Paul Bakker23986e52011-04-24 08:57:21 +0000635 int ret;
636 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000637 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000638 * Buffer should have space for (short) label and decimal formatted MPI,
639 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000640 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000642
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100643 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000644
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100645 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000646
647 if( p == NULL ) p = "";
648
649 plen = strlen( p );
650 slen = strlen( s );
651 s[slen++] = '\r';
652 s[slen++] = '\n';
653
654 if( fout != NULL )
655 {
656 if( fwrite( p, 1, plen, fout ) != plen ||
657 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000659 }
660 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000662
663cleanup:
664
665 return( ret );
666}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000668
669/*
670 * Import X from unsigned binary data, big endian
671 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000673{
Paul Bakker23986e52011-04-24 08:57:21 +0000674 int ret;
675 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000676
677 for( n = 0; n < buflen; n++ )
678 if( buf[n] != 0 )
679 break;
680
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
682 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000683
Paul Bakker23986e52011-04-24 08:57:21 +0000684 for( i = buflen, j = 0; i > n; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000686
687cleanup:
688
689 return( ret );
690}
691
692/*
693 * Export X into unsigned binary data, big endian
694 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000696{
Paul Bakker23986e52011-04-24 08:57:21 +0000697 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200699 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000700
701 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200702 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000703
704 memset( buf, 0, buflen );
705
706 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
707 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
708
709 return( 0 );
710}
711
712/*
713 * Left-shift: X <<= count
714 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200715int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000716{
Paul Bakker23986e52011-04-24 08:57:21 +0000717 int ret;
718 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000720
721 v0 = count / (biL );
722 t1 = count & (biL - 1);
723
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200724 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000725
Paul Bakkerf9688572011-05-05 10:00:45 +0000726 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200727 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000728
729 ret = 0;
730
731 /*
732 * shift by count / limb_size
733 */
734 if( v0 > 0 )
735 {
Paul Bakker23986e52011-04-24 08:57:21 +0000736 for( i = X->n; i > v0; i-- )
737 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000738
Paul Bakker23986e52011-04-24 08:57:21 +0000739 for( ; i > 0; i-- )
740 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000741 }
742
743 /*
744 * shift by count % limb_size
745 */
746 if( t1 > 0 )
747 {
748 for( i = v0; i < X->n; i++ )
749 {
750 r1 = X->p[i] >> (biL - t1);
751 X->p[i] <<= t1;
752 X->p[i] |= r0;
753 r0 = r1;
754 }
755 }
756
757cleanup:
758
759 return( ret );
760}
761
762/*
763 * Right-shift: X >>= count
764 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200765int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000766{
Paul Bakker23986e52011-04-24 08:57:21 +0000767 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200768 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000769
770 v0 = count / biL;
771 v1 = count & (biL - 1);
772
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100773 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200774 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100775
Paul Bakker5121ce52009-01-03 21:22:43 +0000776 /*
777 * shift by count / limb_size
778 */
779 if( v0 > 0 )
780 {
781 for( i = 0; i < X->n - v0; i++ )
782 X->p[i] = X->p[i + v0];
783
784 for( ; i < X->n; i++ )
785 X->p[i] = 0;
786 }
787
788 /*
789 * shift by count % limb_size
790 */
791 if( v1 > 0 )
792 {
Paul Bakker23986e52011-04-24 08:57:21 +0000793 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000794 {
Paul Bakker23986e52011-04-24 08:57:21 +0000795 r1 = X->p[i - 1] << (biL - v1);
796 X->p[i - 1] >>= v1;
797 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000798 r0 = r1;
799 }
800 }
801
802 return( 0 );
803}
804
805/*
806 * Compare unsigned values
807 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200808int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000809{
Paul Bakker23986e52011-04-24 08:57:21 +0000810 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000811
Paul Bakker23986e52011-04-24 08:57:21 +0000812 for( i = X->n; i > 0; i-- )
813 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000814 break;
815
Paul Bakker23986e52011-04-24 08:57:21 +0000816 for( j = Y->n; j > 0; j-- )
817 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000818 break;
819
Paul Bakker23986e52011-04-24 08:57:21 +0000820 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000821 return( 0 );
822
823 if( i > j ) return( 1 );
824 if( j > i ) return( -1 );
825
Paul Bakker23986e52011-04-24 08:57:21 +0000826 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000827 {
Paul Bakker23986e52011-04-24 08:57:21 +0000828 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
829 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000830 }
831
832 return( 0 );
833}
834
835/*
836 * Compare signed values
837 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200838int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000839{
Paul Bakker23986e52011-04-24 08:57:21 +0000840 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000841
Paul Bakker23986e52011-04-24 08:57:21 +0000842 for( i = X->n; i > 0; i-- )
843 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000844 break;
845
Paul Bakker23986e52011-04-24 08:57:21 +0000846 for( j = Y->n; j > 0; j-- )
847 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000848 break;
849
Paul Bakker23986e52011-04-24 08:57:21 +0000850 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000851 return( 0 );
852
853 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000854 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000855
856 if( X->s > 0 && Y->s < 0 ) return( 1 );
857 if( Y->s > 0 && X->s < 0 ) return( -1 );
858
Paul Bakker23986e52011-04-24 08:57:21 +0000859 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000860 {
Paul Bakker23986e52011-04-24 08:57:21 +0000861 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
862 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000863 }
864
865 return( 0 );
866}
867
868/*
869 * Compare signed values
870 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200871int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000872{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200873 mbedtls_mpi Y;
874 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000875
876 *p = ( z < 0 ) ? -z : z;
877 Y.s = ( z < 0 ) ? -1 : 1;
878 Y.n = 1;
879 Y.p = p;
880
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200881 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000882}
883
884/*
885 * Unsigned addition: X = |A| + |B| (HAC 14.7)
886 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200887int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000888{
Paul Bakker23986e52011-04-24 08:57:21 +0000889 int ret;
890 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100891 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000892
893 if( X == B )
894 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200895 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000896 }
897
898 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200899 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200900
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000901 /*
902 * X should always be positive as a result of unsigned additions.
903 */
904 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000905
Paul Bakker23986e52011-04-24 08:57:21 +0000906 for( j = B->n; j > 0; j-- )
907 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000908 break;
909
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200910 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000911
912 o = B->p; p = X->p; c = 0;
913
Janos Follath6c922682015-10-30 17:43:11 +0100914 /*
915 * tmp is used because it might happen that p == o
916 */
Paul Bakker23986e52011-04-24 08:57:21 +0000917 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000918 {
Janos Follath6c922682015-10-30 17:43:11 +0100919 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000920 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100921 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000922 }
923
924 while( c != 0 )
925 {
926 if( i >= X->n )
927 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200928 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000929 p = X->p + i;
930 }
931
Paul Bakker2d319fd2012-09-16 21:34:26 +0000932 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000933 }
934
935cleanup:
936
937 return( ret );
938}
939
940/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000942 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200943static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000944{
Paul Bakker23986e52011-04-24 08:57:21 +0000945 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200946 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000947
948 for( i = c = 0; i < n; i++, s++, d++ )
949 {
950 z = ( *d < c ); *d -= c;
951 c = ( *d < *s ) + z; *d -= *s;
952 }
953
954 while( c != 0 )
955 {
956 z = ( *d < c ); *d -= c;
957 c = z; i++; d++;
958 }
959}
960
961/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100962 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000963 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200964int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000965{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200966 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000967 int ret;
968 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000969
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200970 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
971 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000972
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200973 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000974
975 if( X == B )
976 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000978 B = &TB;
979 }
980
981 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200982 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000983
Paul Bakker1ef7a532009-06-20 10:50:55 +0000984 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100985 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000986 */
987 X->s = 1;
988
Paul Bakker5121ce52009-01-03 21:22:43 +0000989 ret = 0;
990
Paul Bakker23986e52011-04-24 08:57:21 +0000991 for( n = B->n; n > 0; n-- )
992 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000993 break;
994
Paul Bakker23986e52011-04-24 08:57:21 +0000995 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000996
997cleanup:
998
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200999 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001000
1001 return( ret );
1002}
1003
1004/*
1005 * Signed addition: X = A + B
1006 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001007int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001008{
1009 int ret, s = A->s;
1010
1011 if( A->s * B->s < 0 )
1012 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001013 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001014 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001015 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001016 X->s = s;
1017 }
1018 else
1019 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001020 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001021 X->s = -s;
1022 }
1023 }
1024 else
1025 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001026 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001027 X->s = s;
1028 }
1029
1030cleanup:
1031
1032 return( ret );
1033}
1034
1035/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001036 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001037 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001038int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001039{
1040 int ret, s = A->s;
1041
1042 if( A->s * B->s > 0 )
1043 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001044 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001045 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001046 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001047 X->s = s;
1048 }
1049 else
1050 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001051 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001052 X->s = -s;
1053 }
1054 }
1055 else
1056 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001057 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001058 X->s = s;
1059 }
1060
1061cleanup:
1062
1063 return( ret );
1064}
1065
1066/*
1067 * Signed addition: X = A + b
1068 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001069int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001070{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001071 mbedtls_mpi _B;
1072 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001073
1074 p[0] = ( b < 0 ) ? -b : b;
1075 _B.s = ( b < 0 ) ? -1 : 1;
1076 _B.n = 1;
1077 _B.p = p;
1078
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001079 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001080}
1081
1082/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001083 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001084 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001085int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001086{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001087 mbedtls_mpi _B;
1088 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001089
1090 p[0] = ( b < 0 ) ? -b : b;
1091 _B.s = ( b < 0 ) ? -1 : 1;
1092 _B.n = 1;
1093 _B.p = p;
1094
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001095 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001096}
1097
1098/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001099 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001100 */
1101static
1102#if defined(__APPLE__) && defined(__arm__)
1103/*
1104 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1105 * appears to need this to prevent bad ARM code generation at -O3.
1106 */
1107__attribute__ ((noinline))
1108#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001109void 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 +00001110{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001111 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001112
1113#if defined(MULADDC_HUIT)
1114 for( ; i >= 8; i -= 8 )
1115 {
1116 MULADDC_INIT
1117 MULADDC_HUIT
1118 MULADDC_STOP
1119 }
1120
1121 for( ; i > 0; i-- )
1122 {
1123 MULADDC_INIT
1124 MULADDC_CORE
1125 MULADDC_STOP
1126 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001127#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001128 for( ; i >= 16; i -= 16 )
1129 {
1130 MULADDC_INIT
1131 MULADDC_CORE MULADDC_CORE
1132 MULADDC_CORE MULADDC_CORE
1133 MULADDC_CORE MULADDC_CORE
1134 MULADDC_CORE MULADDC_CORE
1135
1136 MULADDC_CORE MULADDC_CORE
1137 MULADDC_CORE MULADDC_CORE
1138 MULADDC_CORE MULADDC_CORE
1139 MULADDC_CORE MULADDC_CORE
1140 MULADDC_STOP
1141 }
1142
1143 for( ; i >= 8; i -= 8 )
1144 {
1145 MULADDC_INIT
1146 MULADDC_CORE MULADDC_CORE
1147 MULADDC_CORE MULADDC_CORE
1148
1149 MULADDC_CORE MULADDC_CORE
1150 MULADDC_CORE MULADDC_CORE
1151 MULADDC_STOP
1152 }
1153
1154 for( ; i > 0; i-- )
1155 {
1156 MULADDC_INIT
1157 MULADDC_CORE
1158 MULADDC_STOP
1159 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001160#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001161
1162 t++;
1163
1164 do {
1165 *d += c; c = ( *d < c ); d++;
1166 }
1167 while( c != 0 );
1168}
1169
1170/*
1171 * Baseline multiplication: X = A * B (HAC 14.12)
1172 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001173int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001174{
Paul Bakker23986e52011-04-24 08:57:21 +00001175 int ret;
1176 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001177 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001178
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001179 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001181 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1182 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001183
Paul Bakker23986e52011-04-24 08:57:21 +00001184 for( i = A->n; i > 0; i-- )
1185 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001186 break;
1187
Paul Bakker23986e52011-04-24 08:57:21 +00001188 for( j = B->n; j > 0; j-- )
1189 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001190 break;
1191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001192 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1193 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001194
Paul Bakker23986e52011-04-24 08:57:21 +00001195 for( i++; j > 0; j-- )
1196 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001197
1198 X->s = A->s * B->s;
1199
1200cleanup:
1201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001202 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001203
1204 return( ret );
1205}
1206
1207/*
1208 * Baseline multiplication: X = A * b
1209 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001210int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001211{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001212 mbedtls_mpi _B;
1213 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001214
1215 _B.s = 1;
1216 _B.n = 1;
1217 _B.p = p;
1218 p[0] = b;
1219
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001220 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001221}
1222
1223/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001224 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1225 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001226 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001227static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1228 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001229{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001230#if defined(MBEDTLS_HAVE_UDBL)
1231 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001232#else
Simon Butcher9803d072016-01-03 00:24:34 +00001233 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1234 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001235 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1236 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001237 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001238#endif
1239
Simon Butcher15b15d12015-11-26 19:35:03 +00001240 /*
1241 * Check for overflow
1242 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001243 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001244 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001245 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001246
Simon Butcherf5ba0452015-12-27 23:01:55 +00001247 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001248 }
1249
1250#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001251 dividend = (mbedtls_t_udbl) u1 << biL;
1252 dividend |= (mbedtls_t_udbl) u0;
1253 quotient = dividend / d;
1254 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1255 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1256
1257 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001258 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001259
1260 return (mbedtls_mpi_uint) quotient;
1261#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001262
1263 /*
1264 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1265 * Vol. 2 - Seminumerical Algorithms, Knuth
1266 */
1267
1268 /*
1269 * Normalize the divisor, d, and dividend, u0, u1
1270 */
1271 s = mbedtls_clz( d );
1272 d = d << s;
1273
1274 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001275 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001276 u0 = u0 << s;
1277
1278 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001279 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001280
1281 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001282 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001283
1284 /*
1285 * Find the first quotient and remainder
1286 */
1287 q1 = u1 / d1;
1288 r0 = u1 - d1 * q1;
1289
1290 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1291 {
1292 q1 -= 1;
1293 r0 += d1;
1294
1295 if ( r0 >= radix ) break;
1296 }
1297
Simon Butcherf5ba0452015-12-27 23:01:55 +00001298 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001299 q0 = rAX / d1;
1300 r0 = rAX - q0 * d1;
1301
1302 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1303 {
1304 q0 -= 1;
1305 r0 += d1;
1306
1307 if ( r0 >= radix ) break;
1308 }
1309
1310 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001311 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001312
1313 quotient = q1 * radix + q0;
1314
1315 return quotient;
1316#endif
1317}
1318
1319/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001320 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001321 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001322int 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 +00001323{
Paul Bakker23986e52011-04-24 08:57:21 +00001324 int ret;
1325 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001326 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001327
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001328 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1329 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001330
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001331 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1332 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001334 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001335 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1337 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001338 return( 0 );
1339 }
1340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001341 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1342 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001343 X.s = Y.s = 1;
1344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001345 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1346 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1347 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1348 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001349
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001350 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001351 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001352 {
1353 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001354 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1355 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001356 }
1357 else k = 0;
1358
1359 n = X.n - 1;
1360 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001361 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001362
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001363 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001364 {
1365 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001367 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001368 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001369
1370 for( i = n; i > t ; i-- )
1371 {
1372 if( X.p[i] >= Y.p[t] )
1373 Z.p[i - t - 1] = ~0;
1374 else
1375 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001376 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1377 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001378 }
1379
1380 Z.p[i - t - 1]++;
1381 do
1382 {
1383 Z.p[i - t - 1]--;
1384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001385 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001386 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001387 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001388 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001391 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1392 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001393 T2.p[2] = X.p[i];
1394 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001395 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001397 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1398 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1399 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001400
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001401 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001402 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1404 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1405 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001406 Z.p[i - t - 1]--;
1407 }
1408 }
1409
1410 if( Q != NULL )
1411 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001412 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001413 Q->s = A->s * B->s;
1414 }
1415
1416 if( R != NULL )
1417 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001418 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001419 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001420 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001421
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001422 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001423 R->s = 1;
1424 }
1425
1426cleanup:
1427
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001428 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1429 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001430
1431 return( ret );
1432}
1433
1434/*
1435 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001436 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001437int 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 +00001438{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001439 mbedtls_mpi _B;
1440 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001441
1442 p[0] = ( b < 0 ) ? -b : b;
1443 _B.s = ( b < 0 ) ? -1 : 1;
1444 _B.n = 1;
1445 _B.p = p;
1446
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001447 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001448}
1449
1450/*
1451 * Modulo: R = A mod B
1452 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001453int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001454{
1455 int ret;
1456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001457 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1458 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001460 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001461
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001462 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1463 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001465 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1466 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001467
1468cleanup:
1469
1470 return( ret );
1471}
1472
1473/*
1474 * Modulo: r = A mod b
1475 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001476int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001477{
Paul Bakker23986e52011-04-24 08:57:21 +00001478 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001479 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001480
1481 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001482 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001483
1484 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001485 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001486
1487 /*
1488 * handle trivial cases
1489 */
1490 if( b == 1 )
1491 {
1492 *r = 0;
1493 return( 0 );
1494 }
1495
1496 if( b == 2 )
1497 {
1498 *r = A->p[0] & 1;
1499 return( 0 );
1500 }
1501
1502 /*
1503 * general case
1504 */
Paul Bakker23986e52011-04-24 08:57:21 +00001505 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001506 {
Paul Bakker23986e52011-04-24 08:57:21 +00001507 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001508 y = ( y << biH ) | ( x >> biH );
1509 z = y / b;
1510 y -= z * b;
1511
1512 x <<= biH;
1513 y = ( y << biH ) | ( x >> biH );
1514 z = y / b;
1515 y -= z * b;
1516 }
1517
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001518 /*
1519 * If A is negative, then the current y represents a negative value.
1520 * Flipping it to the positive side.
1521 */
1522 if( A->s < 0 && y != 0 )
1523 y = b - y;
1524
Paul Bakker5121ce52009-01-03 21:22:43 +00001525 *r = y;
1526
1527 return( 0 );
1528}
1529
1530/*
1531 * Fast Montgomery initialization (thanks to Tom St Denis)
1532 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001533static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001534{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001535 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001536 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001537
1538 x = m0;
1539 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001540
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001541 for( i = biL; i >= 8; i /= 2 )
1542 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001543
1544 *mm = ~x + 1;
1545}
1546
1547/*
1548 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1549 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001550static 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 +02001551 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001552{
Paul Bakker23986e52011-04-24 08:57:21 +00001553 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001554 mbedtls_mpi_uint u0, u1, *d;
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001555
1556 if( T->n < N->n + 1 || T->p == NULL )
1557 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001558
1559 memset( T->p, 0, T->n * ciL );
1560
1561 d = T->p;
1562 n = N->n;
1563 m = ( B->n < n ) ? B->n : n;
1564
1565 for( i = 0; i < n; i++ )
1566 {
1567 /*
1568 * T = (T + u0*B + u1*N) / 2^biL
1569 */
1570 u0 = A->p[i];
1571 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1572
1573 mpi_mul_hlp( m, B->p, d, u0 );
1574 mpi_mul_hlp( n, N->p, d, u1 );
1575
1576 *d++ = u0; d[n + 1] = 0;
1577 }
1578
Paul Bakker66d5d072014-06-17 16:39:18 +02001579 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001580
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001581 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001582 mpi_sub_hlp( n, N->p, A->p );
1583 else
1584 /* prevent timing attacks */
1585 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001586
1587 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001588}
1589
1590/*
1591 * Montgomery reduction: A = A * R^-1 mod N
1592 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001593static 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 +00001594{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001595 mbedtls_mpi_uint z = 1;
1596 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001597
Paul Bakker8ddb6452013-02-27 14:56:33 +01001598 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001599 U.p = &z;
1600
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001601 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001602}
1603
1604/*
1605 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1606 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001607int 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 +00001608{
Paul Bakker23986e52011-04-24 08:57:21 +00001609 int ret;
1610 size_t wbits, wsize, one = 1;
1611 size_t i, j, nblimbs;
1612 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001613 mbedtls_mpi_uint ei, mm, state;
1614 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001615 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001617 if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
1618 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001619
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001620 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1621 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001622
1623 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001624 * Init temps and window size
1625 */
1626 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001627 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1628 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001629 memset( W, 0, sizeof( W ) );
1630
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001631 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001632
1633 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1634 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1637 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001638
Paul Bakker5121ce52009-01-03 21:22:43 +00001639 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001640 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1641 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1642 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001643
1644 /*
Paul Bakker50546922012-05-19 08:40:49 +00001645 * Compensate for negative A (and correct at the end)
1646 */
1647 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001648 if( neg )
1649 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001650 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001651 Apos.s = 1;
1652 A = &Apos;
1653 }
1654
1655 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001656 * If 1st call, pre-compute R^2 mod N
1657 */
1658 if( _RR == NULL || _RR->p == NULL )
1659 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001660 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1661 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1662 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001663
1664 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001665 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001666 }
1667 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001668 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001669
1670 /*
1671 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1672 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001673 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1674 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001675 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001676 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001677
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001678 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001679
1680 /*
1681 * X = R^2 * R^-1 mod N = R mod N
1682 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001683 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001684 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001685
1686 if( wsize > 1 )
1687 {
1688 /*
1689 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1690 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001691 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001692
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001693 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1694 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001695
1696 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001697 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001698
Paul Bakker5121ce52009-01-03 21:22:43 +00001699 /*
1700 * W[i] = W[i - 1] * W[1]
1701 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001702 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001703 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001704 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1705 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001706
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001707 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001708 }
1709 }
1710
1711 nblimbs = E->n;
1712 bufsize = 0;
1713 nbits = 0;
1714 wbits = 0;
1715 state = 0;
1716
1717 while( 1 )
1718 {
1719 if( bufsize == 0 )
1720 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001721 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001722 break;
1723
Paul Bakker0d7702c2013-10-29 16:18:35 +01001724 nblimbs--;
1725
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001726 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001727 }
1728
1729 bufsize--;
1730
1731 ei = (E->p[nblimbs] >> bufsize) & 1;
1732
1733 /*
1734 * skip leading 0s
1735 */
1736 if( ei == 0 && state == 0 )
1737 continue;
1738
1739 if( ei == 0 && state == 1 )
1740 {
1741 /*
1742 * out of window, square X
1743 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001744 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001745 continue;
1746 }
1747
1748 /*
1749 * add ei to current window
1750 */
1751 state = 2;
1752
1753 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001754 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001755
1756 if( nbits == wsize )
1757 {
1758 /*
1759 * X = X^wsize R^-1 mod N
1760 */
1761 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001762 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001763
1764 /*
1765 * X = X * W[wbits] R^-1 mod N
1766 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001767 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001768
1769 state--;
1770 nbits = 0;
1771 wbits = 0;
1772 }
1773 }
1774
1775 /*
1776 * process the remaining bits
1777 */
1778 for( i = 0; i < nbits; i++ )
1779 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001780 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001781
1782 wbits <<= 1;
1783
Paul Bakker66d5d072014-06-17 16:39:18 +02001784 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001785 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001786 }
1787
1788 /*
1789 * X = A^E * R * R^-1 mod N = A^E mod N
1790 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001791 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001792
Hanno Beckera4af1c42017-04-18 09:07:45 +01001793 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001794 {
1795 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001796 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001797 }
1798
Paul Bakker5121ce52009-01-03 21:22:43 +00001799cleanup:
1800
Paul Bakker66d5d072014-06-17 16:39:18 +02001801 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001802 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001803
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001804 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001805
Paul Bakker75a28602014-03-31 12:08:17 +02001806 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001807 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001808
1809 return( ret );
1810}
1811
Paul Bakker5121ce52009-01-03 21:22:43 +00001812/*
1813 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1814 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001815int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001816{
Paul Bakker23986e52011-04-24 08:57:21 +00001817 int ret;
1818 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001819 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001820
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001821 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001822
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001823 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1824 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001825
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001826 lz = mbedtls_mpi_lsb( &TA );
1827 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001828
Paul Bakker66d5d072014-06-17 16:39:18 +02001829 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001830 lz = lzt;
1831
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001832 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1833 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001834
1835 TA.s = TB.s = 1;
1836
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001837 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001838 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001839 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1840 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001841
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001842 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001843 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1845 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846 }
1847 else
1848 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001849 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1850 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001851 }
1852 }
1853
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001854 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1855 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001856
1857cleanup:
1858
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001859 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001860
1861 return( ret );
1862}
1863
Paul Bakker33dc46b2014-04-30 16:11:39 +02001864/*
1865 * Fill X with size bytes of random.
1866 *
1867 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001868 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001869 * deterministic, eg for tests).
1870 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001871int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001872 int (*f_rng)(void *, unsigned char *, size_t),
1873 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001874{
Paul Bakker23986e52011-04-24 08:57:21 +00001875 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001876 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001877
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001878 if( size > MBEDTLS_MPI_MAX_SIZE )
1879 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001880
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001881 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1882 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001883
1884cleanup:
1885 return( ret );
1886}
1887
Paul Bakker5121ce52009-01-03 21:22:43 +00001888/*
1889 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1890 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001891int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001892{
1893 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001895
Hanno Becker4bcb4912017-04-18 15:49:39 +01001896 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001897 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001898
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001899 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1900 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1901 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001902
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001903 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001904
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001905 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001906 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001907 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001908 goto cleanup;
1909 }
1910
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001911 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1912 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1913 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1914 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001915
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001916 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1917 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1918 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1919 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001920
1921 do
1922 {
1923 while( ( TU.p[0] & 1 ) == 0 )
1924 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001925 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001926
1927 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1928 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1930 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001931 }
1932
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001933 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1934 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001935 }
1936
1937 while( ( TV.p[0] & 1 ) == 0 )
1938 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001939 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001940
1941 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1942 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001943 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1944 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945 }
1946
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001947 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1948 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001949 }
1950
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001951 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001952 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001953 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1954 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1955 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956 }
1957 else
1958 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1960 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1961 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001962 }
1963 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001964 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001965
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001966 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1967 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001968
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001969 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1970 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001971
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001972 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001973
1974cleanup:
1975
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001976 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1977 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1978 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001979
1980 return( ret );
1981}
1982
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001983#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001984
Paul Bakker5121ce52009-01-03 21:22:43 +00001985static const int small_prime[] =
1986{
1987 3, 5, 7, 11, 13, 17, 19, 23,
1988 29, 31, 37, 41, 43, 47, 53, 59,
1989 61, 67, 71, 73, 79, 83, 89, 97,
1990 101, 103, 107, 109, 113, 127, 131, 137,
1991 139, 149, 151, 157, 163, 167, 173, 179,
1992 181, 191, 193, 197, 199, 211, 223, 227,
1993 229, 233, 239, 241, 251, 257, 263, 269,
1994 271, 277, 281, 283, 293, 307, 311, 313,
1995 317, 331, 337, 347, 349, 353, 359, 367,
1996 373, 379, 383, 389, 397, 401, 409, 419,
1997 421, 431, 433, 439, 443, 449, 457, 461,
1998 463, 467, 479, 487, 491, 499, 503, 509,
1999 521, 523, 541, 547, 557, 563, 569, 571,
2000 577, 587, 593, 599, 601, 607, 613, 617,
2001 619, 631, 641, 643, 647, 653, 659, 661,
2002 673, 677, 683, 691, 701, 709, 719, 727,
2003 733, 739, 743, 751, 757, 761, 769, 773,
2004 787, 797, 809, 811, 821, 823, 827, 829,
2005 839, 853, 857, 859, 863, 877, 881, 883,
2006 887, 907, 911, 919, 929, 937, 941, 947,
2007 953, 967, 971, 977, 983, 991, 997, -103
2008};
2009
2010/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002011 * Small divisors test (X must be positive)
2012 *
2013 * Return values:
2014 * 0: no small factor (possible prime, more tests needed)
2015 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002017 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002018 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002019static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002020{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002021 int ret = 0;
2022 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002024
Paul Bakker5121ce52009-01-03 21:22:43 +00002025 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002026 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002027
2028 for( i = 0; small_prime[i] > 0; i++ )
2029 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002030 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002031 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002032
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002033 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002034
2035 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002036 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002037 }
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002038
2039cleanup:
2040 return( ret );
2041}
2042
2043/*
2044 * Miller-Rabin pseudo-primality test (HAC 4.24)
2045 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002047 int (*f_rng)(void *, unsigned char *, size_t),
2048 void *p_rng )
2049{
Pascal Junodb99183d2015-03-11 16:49:45 +01002050 int ret, count;
2051 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002053
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002054 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2055 mbedtls_mpi_init( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002056
2057 /*
2058 * W = |X| - 1
2059 * R = W >> lsb( W )
2060 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002061 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2062 s = mbedtls_mpi_lsb( &W );
2063 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2064 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002065
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002066 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002067 /*
2068 * HAC, table 4.4
2069 */
2070 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2071 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2072 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2073
2074 for( i = 0; i < n; i++ )
2075 {
2076 /*
2077 * pick a random A, 1 < A < |X| - 1
2078 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002079 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002080
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002081 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00002082 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002083 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002084 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00002085 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002086 A.p[0] |= 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002087
Pascal Junodb99183d2015-03-11 16:49:45 +01002088 count = 0;
2089 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002090 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002091
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002092 j = mbedtls_mpi_bitlen( &A );
2093 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002094 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002095 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002096 }
2097
2098 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002099 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002100 }
2101
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002102 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2103 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002104
2105 /*
2106 * A = A^R mod |X|
2107 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002108 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002110 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2111 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002112 continue;
2113
2114 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002115 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002116 {
2117 /*
2118 * A = A * A mod |X|
2119 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002120 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2121 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002123 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002124 break;
2125
2126 j++;
2127 }
2128
2129 /*
2130 * not prime if A != |X| - 1 or A == 1
2131 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002132 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2133 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002134 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002135 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002136 break;
2137 }
2138 }
2139
2140cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002141 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2142 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002143
2144 return( ret );
2145}
2146
2147/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002148 * Pseudo-primality test: small factors, then Miller-Rabin
2149 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002150int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002151 int (*f_rng)(void *, unsigned char *, size_t),
2152 void *p_rng )
2153{
2154 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002155 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002156
2157 XX.s = 1;
2158 XX.n = X->n;
2159 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002160
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002161 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2162 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2163 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002164
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002165 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002166 return( 0 );
2167
2168 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2169 {
2170 if( ret == 1 )
2171 return( 0 );
2172
2173 return( ret );
2174 }
2175
2176 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2177}
2178
2179/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002180 * Prime number generation
2181 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002182int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002183 int (*f_rng)(void *, unsigned char *, size_t),
2184 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002185{
Paul Bakker23986e52011-04-24 08:57:21 +00002186 int ret;
2187 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188 mbedtls_mpi_uint r;
2189 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002190
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002191 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2192 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002193
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002194 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002195
2196 n = BITS_TO_LIMBS( nbits );
2197
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002199
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002200 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002201 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002202
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002203 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002204
2205 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002206
2207 if( dh_flag == 0 )
2208 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002209 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002210 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002211 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002212 goto cleanup;
2213
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002214 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002215 }
2216 }
2217 else
2218 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002219 /*
2220 * An necessary condition for Y and X = 2Y + 1 to be prime
2221 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2222 * Make sure it is satisfied, while keeping X = 3 mod 4
2223 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002224
2225 X->p[0] |= 2;
2226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002227 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002228 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002229 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002230 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002231 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002232
2233 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002234 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2235 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002236
2237 while( 1 )
2238 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002239 /*
2240 * First, check small factors for X and Y
2241 * before doing Miller-Rabin on any of them
2242 */
2243 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2244 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2245 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2246 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002247 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002248 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002249 }
2250
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002251 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002252 goto cleanup;
2253
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002254 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002255 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002256 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2257 * so up Y by 6 and X by 12.
2258 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002259 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2260 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002261 }
2262 }
2263
2264cleanup:
2265
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002266 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002267
2268 return( ret );
2269}
2270
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002271#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002272
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002273#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002274
Paul Bakker23986e52011-04-24 08:57:21 +00002275#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002276
2277static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2278{
2279 { 693, 609, 21 },
2280 { 1764, 868, 28 },
2281 { 768454923, 542167814, 1 }
2282};
2283
Paul Bakker5121ce52009-01-03 21:22:43 +00002284/*
2285 * Checkup routine
2286 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002287int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002288{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002289 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002290 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002291
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002292 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2293 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002294
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002295 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002296 "EFE021C2645FD1DC586E69184AF4A31E" \
2297 "D5F53E93B5F123FA41680867BA110131" \
2298 "944FE7952E2517337780CB0DB80E61AA" \
2299 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2300
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002301 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002302 "B2E7EFD37075B9F03FF989C7C5051C20" \
2303 "34D2A323810251127E7BF8625A4F49A5" \
2304 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2305 "5B5C25763222FEFCCFC38B832366C29E" ) );
2306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002308 "0066A198186C18C10B2F5ED9B522752A" \
2309 "9830B69916E535C8F047518A889A43A5" \
2310 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2311
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002312 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002313
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002314 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002315 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2316 "9E857EA95A03512E2BAE7391688D264A" \
2317 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2318 "8001B72E848A38CAE1C65F78E56ABDEF" \
2319 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2320 "ECF677152EF804370C1A305CAF3B5BF1" \
2321 "30879B56C61DE584A0F53A2447A51E" ) );
2322
2323 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002324 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002326 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002327 {
2328 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002329 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002330
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002331 ret = 1;
2332 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002333 }
2334
2335 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002336 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002340 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002341 "256567336059E52CAE22925474705F39A94" ) );
2342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002343 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002344 "6613F26162223DF488E9CD48CC132C7A" \
2345 "0AC93C701B001B092E4E5B9F73BCD27B" \
2346 "9EE50D0657C77F374E903CDFA4C642" ) );
2347
2348 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002349 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002350
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002351 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2352 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002353 {
2354 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002355 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002356
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002357 ret = 1;
2358 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002359 }
2360
2361 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002362 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002363
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002364 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002366 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002367 "36E139AEA55215609D2816998ED020BB" \
2368 "BD96C37890F65171D948E9BC7CBAA4D9" \
2369 "325D24D6A3C12710F10A09FA08AB87" ) );
2370
2371 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002372 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002373
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002374 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002375 {
2376 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002377 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002378
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002379 ret = 1;
2380 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002381 }
2382
2383 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002384 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002385
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002386 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002387
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002388 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002389 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2390 "C3DBA76456363A10869622EAC2DD84EC" \
2391 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2392
2393 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002394 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002397 {
2398 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002399 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002400
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002401 ret = 1;
2402 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002403 }
2404
2405 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002406 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002407
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002408 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002409 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002410
Paul Bakker66d5d072014-06-17 16:39:18 +02002411 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002412 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002413 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2414 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002415
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002416 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002417
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002418 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002419 {
2420 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002421 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002422
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002423 ret = 1;
2424 goto cleanup;
2425 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002426 }
2427
2428 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002429 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002430
Paul Bakker5121ce52009-01-03 21:22:43 +00002431cleanup:
2432
2433 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002435
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002436 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2437 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002438
2439 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002441
2442 return( ret );
2443}
2444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002445#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002446
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002447#endif /* MBEDTLS_BIGNUM_C */