blob: 584ab85a3056b3ef9dcc30e2404416f51d8d7a81 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
Paul Bakkerb96f1542010-07-18 20:36:00 +00005 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +00006 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakkerb96f1542010-07-18 20:36:00 +00007 *
Paul Bakker5121ce52009-01-03 21:22:43 +00008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
Simon Butchere4ed3472015-12-22 15:26:57 +000022
Paul Bakker5121ce52009-01-03 21:22:43 +000023/*
Simon Butchere4ed3472015-12-22 15:26:57 +000024 * The following sources were referenced in the design of this Multi-precision
25 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000026 *
Simon Butchere4ed3472015-12-22 15:26:57 +000027 * [1] Handbook of Applied Cryptography - 1997
28 * Menezes, van Oorschot and Vanstone
29 *
30 * [2] Multi-Precision Math
31 * Tom St Denis
32 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
33 *
34 * [3] GNU Multi-Precision Arithmetic Library
35 * https://gmplib.org/manual/index.html
36 *
37*/
Paul Bakker5121ce52009-01-03 21:22:43 +000038
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020039#if !defined(POLARSSL_CONFIG_FILE)
Paul Bakker40e46942009-01-03 21:51:57 +000040#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020041#else
42#include POLARSSL_CONFIG_FILE
43#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000044
Paul Bakker40e46942009-01-03 21:51:57 +000045#if defined(POLARSSL_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000046
Paul Bakker40e46942009-01-03 21:51:57 +000047#include "polarssl/bignum.h"
48#include "polarssl/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000049
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <string.h>
51
Paul Bakker7dc4c442014-02-01 22:50:26 +010052#if defined(POLARSSL_PLATFORM_C)
53#include "polarssl/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020054#else
Rich Evans00ab4702015-02-06 13:43:58 +000055#include <stdio.h>
56#include <stdlib.h>
Paul Bakker7dc4c442014-02-01 22:50:26 +010057#define polarssl_printf printf
Paul Bakker6e339b52013-07-03 13:37:05 +020058#define polarssl_malloc malloc
59#define polarssl_free free
60#endif
61
Paul Bakker34617722014-06-13 17:20:13 +020062/* Implementation that should never be optimized out by the compiler */
63static void polarssl_zeroize( void *v, size_t n ) {
64 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
65}
66
Paul Bakkerf9688572011-05-05 10:00:45 +000067#define ciL (sizeof(t_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000068#define biL (ciL << 3) /* bits in limb */
69#define biH (ciL << 2) /* half limb size */
70
Manuel Pégourié-Gonnardfa647a72015-10-05 15:23:11 +010071#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
72
Paul Bakker5121ce52009-01-03 21:22:43 +000073/*
74 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard59efb6a2015-09-28 13:48:04 +020075 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000076 */
Manuel Pégourié-Gonnard59efb6a2015-09-28 13:48:04 +020077#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
78#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000079
80/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000081 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000082 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000083void mpi_init( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000084{
Paul Bakker6c591fa2011-05-05 11:49:20 +000085 if( X == NULL )
86 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000087
Paul Bakker6c591fa2011-05-05 11:49:20 +000088 X->s = 1;
89 X->n = 0;
90 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000091}
92
93/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000094 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000095 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000096void mpi_free( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000097{
Paul Bakker6c591fa2011-05-05 11:49:20 +000098 if( X == NULL )
99 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000100
Paul Bakker6c591fa2011-05-05 11:49:20 +0000101 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102 {
Paul Bakker34617722014-06-13 17:20:13 +0200103 polarssl_zeroize( X->p, X->n * ciL );
Paul Bakker6e339b52013-07-03 13:37:05 +0200104 polarssl_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000105 }
106
Paul Bakker6c591fa2011-05-05 11:49:20 +0000107 X->s = 1;
108 X->n = 0;
109 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000110}
111
112/*
113 * Enlarge to the specified number of limbs
114 */
Paul Bakker23986e52011-04-24 08:57:21 +0000115int mpi_grow( mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000116{
Paul Bakkera755ca12011-04-24 09:11:17 +0000117 t_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000118
Paul Bakkerf9688572011-05-05 10:00:45 +0000119 if( nblimbs > POLARSSL_MPI_MAX_LIMBS )
Paul Bakker69e095c2011-12-10 21:55:01 +0000120 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000121
Paul Bakker5121ce52009-01-03 21:22:43 +0000122 if( X->n < nblimbs )
123 {
Mansour Moufidc531b4a2015-02-15 17:35:38 -0500124 if( ( p = polarssl_malloc( nblimbs * ciL ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000125 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000126
127 memset( p, 0, nblimbs * ciL );
128
129 if( X->p != NULL )
130 {
131 memcpy( p, X->p, X->n * ciL );
Paul Bakker34617722014-06-13 17:20:13 +0200132 polarssl_zeroize( X->p, X->n * ciL );
Paul Bakker6e339b52013-07-03 13:37:05 +0200133 polarssl_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000134 }
135
136 X->n = nblimbs;
137 X->p = p;
138 }
139
140 return( 0 );
141}
142
143/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100144 * Resize down as much as possible,
145 * while keeping at least the specified number of limbs
146 */
147int mpi_shrink( mpi *X, size_t nblimbs )
148{
149 t_uint *p;
150 size_t i;
151
152 /* Actually resize up in this case */
153 if( X->n <= nblimbs )
154 return( mpi_grow( X, nblimbs ) );
155
156 for( i = X->n - 1; i > 0; i-- )
157 if( X->p[i] != 0 )
158 break;
159 i++;
160
161 if( i < nblimbs )
162 i = nblimbs;
163
Mansour Moufidc531b4a2015-02-15 17:35:38 -0500164 if( ( p = polarssl_malloc( i * ciL ) ) == NULL )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100165 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
166
167 memset( p, 0, i * ciL );
168
169 if( X->p != NULL )
170 {
171 memcpy( p, X->p, i * ciL );
Paul Bakker34617722014-06-13 17:20:13 +0200172 polarssl_zeroize( X->p, X->n * ciL );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100173 polarssl_free( X->p );
174 }
175
176 X->n = i;
177 X->p = p;
178
179 return( 0 );
180}
181
182/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000183 * Copy the contents of Y into X
184 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000185int mpi_copy( mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000186{
Paul Bakker23986e52011-04-24 08:57:21 +0000187 int ret;
188 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000189
190 if( X == Y )
191 return( 0 );
192
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200193 if( Y->p == NULL )
194 {
195 mpi_free( X );
196 return( 0 );
197 }
198
Paul Bakker5121ce52009-01-03 21:22:43 +0000199 for( i = Y->n - 1; i > 0; i-- )
200 if( Y->p[i] != 0 )
201 break;
202 i++;
203
204 X->s = Y->s;
205
206 MPI_CHK( mpi_grow( X, i ) );
207
208 memset( X->p, 0, X->n * ciL );
209 memcpy( X->p, Y->p, i * ciL );
210
211cleanup:
212
213 return( ret );
214}
215
216/*
217 * Swap the contents of X and Y
218 */
219void mpi_swap( mpi *X, mpi *Y )
220{
221 mpi T;
222
223 memcpy( &T, X, sizeof( mpi ) );
224 memcpy( X, Y, sizeof( mpi ) );
225 memcpy( Y, &T, sizeof( mpi ) );
226}
227
228/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100229 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100230 * about whether the assignment was made or not.
231 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100232 */
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100233int mpi_safe_cond_assign( mpi *X, const mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100234{
235 int ret = 0;
236 size_t i;
237
Pascal Junodb99183d2015-03-11 16:49:45 +0100238 /* make sure assign is 0 or 1 in a time-constant manner */
239 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100240
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100241 MPI_CHK( mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100242
Paul Bakker66d5d072014-06-17 16:39:18 +0200243 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100244
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100245 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200246 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100247
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100248 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200249 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250
251cleanup:
252 return( ret );
253}
254
255/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100256 * Conditionally swap X and Y, without leaking information
257 * about whether the swap was made or not.
258 * Here it is not ok to simply swap the pointers, which whould lead to
259 * different memory access patterns when X and Y are used afterwards.
260 */
261int mpi_safe_cond_swap( mpi *X, mpi *Y, unsigned char swap )
262{
263 int ret, s;
264 size_t i;
265 t_uint tmp;
266
267 if( X == Y )
268 return( 0 );
269
Pascal Junodb99183d2015-03-11 16:49:45 +0100270 /* make sure swap is 0 or 1 in a time-constant manner */
271 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100272
273 MPI_CHK( mpi_grow( X, Y->n ) );
274 MPI_CHK( mpi_grow( Y, X->n ) );
275
276 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200277 X->s = X->s * ( 1 - swap ) + Y->s * swap;
278 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100279
280
281 for( i = 0; i < X->n; i++ )
282 {
283 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200284 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
285 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286 }
287
288cleanup:
289 return( ret );
290}
291
292/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000293 * Set value from integer
294 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000295int mpi_lset( mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000296{
297 int ret;
298
299 MPI_CHK( mpi_grow( X, 1 ) );
300 memset( X->p, 0, X->n * ciL );
301
302 X->p[0] = ( z < 0 ) ? -z : z;
303 X->s = ( z < 0 ) ? -1 : 1;
304
305cleanup:
306
307 return( ret );
308}
309
310/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000311 * Get a specific bit
312 */
Paul Bakker6b906e52012-05-08 12:01:43 +0000313int mpi_get_bit( const mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000314{
315 if( X->n * biL <= pos )
316 return( 0 );
317
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200318 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000319}
320
321/*
322 * Set a bit to a specific value of 0 or 1
323 */
324int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
325{
326 int ret = 0;
327 size_t off = pos / biL;
328 size_t idx = pos % biL;
329
330 if( val != 0 && val != 1 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200331 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200332
Paul Bakker2f5947e2011-05-18 15:47:11 +0000333 if( X->n * biL <= pos )
334 {
335 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200336 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000337
338 MPI_CHK( mpi_grow( X, off + 1 ) );
339 }
340
Manuel Pégourié-Gonnard9a4a5ac2013-12-04 18:05:29 +0100341 X->p[off] &= ~( (t_uint) 0x01 << idx );
342 X->p[off] |= (t_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000343
344cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200345
Paul Bakker2f5947e2011-05-18 15:47:11 +0000346 return( ret );
347}
348
349/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000350 * Return the number of least significant bits
351 */
Paul Bakker23986e52011-04-24 08:57:21 +0000352size_t mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000353{
Paul Bakker23986e52011-04-24 08:57:21 +0000354 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000355
356 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000357 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000358 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
359 return( count );
360
361 return( 0 );
362}
363
364/*
Simon Butchere4ed3472015-12-22 15:26:57 +0000365 * Count leading zero bits in a given integer
366 */
367static size_t int_clz( const t_uint x )
368{
369 size_t j;
370 t_uint mask = (t_uint) 1 << (biL - 1);
371
372 for( j = 0; j < biL; j++ )
373 {
374 if( x & mask ) break;
375
376 mask >>= 1;
377 }
378
379 return j;
380}
381
382/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000383 * Return the number of most significant bits
384 */
Paul Bakker23986e52011-04-24 08:57:21 +0000385size_t mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000386{
Paul Bakker23986e52011-04-24 08:57:21 +0000387 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000388
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200389 if( X->n == 0 )
390 return( 0 );
391
Paul Bakker5121ce52009-01-03 21:22:43 +0000392 for( i = X->n - 1; i > 0; i-- )
393 if( X->p[i] != 0 )
394 break;
395
Simon Butchere4ed3472015-12-22 15:26:57 +0000396 j = biL - int_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000397
Paul Bakker23986e52011-04-24 08:57:21 +0000398 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000399}
400
401/*
402 * Return the total size in bytes
403 */
Paul Bakker23986e52011-04-24 08:57:21 +0000404size_t mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000405{
406 return( ( mpi_msb( X ) + 7 ) >> 3 );
407}
408
409/*
410 * Convert an ASCII character to digit value
411 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000412static int mpi_get_digit( t_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000413{
414 *d = 255;
415
416 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
417 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
418 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
419
Paul Bakkera755ca12011-04-24 09:11:17 +0000420 if( *d >= (t_uint) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000421 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000422
423 return( 0 );
424}
425
426/*
427 * Import from an ASCII string
428 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000429int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000430{
Paul Bakker23986e52011-04-24 08:57:21 +0000431 int ret;
432 size_t i, j, slen, n;
Paul Bakkera755ca12011-04-24 09:11:17 +0000433 t_uint d;
Paul Bakker5121ce52009-01-03 21:22:43 +0000434 mpi T;
435
436 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000437 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000438
Paul Bakker6c591fa2011-05-05 11:49:20 +0000439 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000440
Paul Bakkerff60ee62010-03-16 21:09:09 +0000441 slen = strlen( s );
442
Paul Bakker5121ce52009-01-03 21:22:43 +0000443 if( radix == 16 )
444 {
Manuel Pégourié-Gonnardfa647a72015-10-05 15:23:11 +0100445 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard59efb6a2015-09-28 13:48:04 +0200446 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
447
Paul Bakkerff60ee62010-03-16 21:09:09 +0000448 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000449
450 MPI_CHK( mpi_grow( X, n ) );
451 MPI_CHK( mpi_lset( X, 0 ) );
452
Paul Bakker23986e52011-04-24 08:57:21 +0000453 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000454 {
Paul Bakker23986e52011-04-24 08:57:21 +0000455 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000456 {
457 X->s = -1;
458 break;
459 }
460
Paul Bakker23986e52011-04-24 08:57:21 +0000461 MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200462 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000463 }
464 }
465 else
466 {
467 MPI_CHK( mpi_lset( X, 0 ) );
468
Paul Bakkerff60ee62010-03-16 21:09:09 +0000469 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000470 {
471 if( i == 0 && s[i] == '-' )
472 {
473 X->s = -1;
474 continue;
475 }
476
477 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
478 MPI_CHK( mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000479
480 if( X->s == 1 )
481 {
482 MPI_CHK( mpi_add_int( X, &T, d ) );
483 }
484 else
485 {
486 MPI_CHK( mpi_sub_int( X, &T, d ) );
487 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000488 }
489 }
490
491cleanup:
492
Paul Bakker6c591fa2011-05-05 11:49:20 +0000493 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494
495 return( ret );
496}
497
498/*
499 * Helper to write the digits high-order first
500 */
501static int mpi_write_hlp( mpi *X, int radix, char **p )
502{
503 int ret;
Paul Bakkera755ca12011-04-24 09:11:17 +0000504 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000505
506 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000507 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000508
509 MPI_CHK( mpi_mod_int( &r, X, radix ) );
510 MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
511
512 if( mpi_cmp_int( X, 0 ) != 0 )
513 MPI_CHK( mpi_write_hlp( X, radix, p ) );
514
515 if( r < 10 )
516 *(*p)++ = (char)( r + 0x30 );
517 else
518 *(*p)++ = (char)( r + 0x37 );
519
520cleanup:
521
522 return( ret );
523}
524
525/*
526 * Export into an ASCII string
527 */
Paul Bakker23986e52011-04-24 08:57:21 +0000528int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000529{
Paul Bakker23986e52011-04-24 08:57:21 +0000530 int ret = 0;
531 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000532 char *p;
533 mpi T;
534
535 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000536 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000537
538 n = mpi_msb( X );
539 if( radix >= 4 ) n >>= 1;
540 if( radix >= 16 ) n >>= 1;
541 n += 3;
542
543 if( *slen < n )
544 {
545 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000546 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000547 }
548
549 p = s;
Paul Bakker6c591fa2011-05-05 11:49:20 +0000550 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000551
552 if( X->s == -1 )
553 *p++ = '-';
554
555 if( radix == 16 )
556 {
Paul Bakker23986e52011-04-24 08:57:21 +0000557 int c;
558 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000559
Paul Bakker23986e52011-04-24 08:57:21 +0000560 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000561 {
Paul Bakker23986e52011-04-24 08:57:21 +0000562 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000563 {
Paul Bakker23986e52011-04-24 08:57:21 +0000564 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000565
Paul Bakker6c343d72014-07-10 14:36:19 +0200566 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000567 continue;
568
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000569 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000570 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000571 k = 1;
572 }
573 }
574 }
575 else
576 {
577 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000578
579 if( T.s == -1 )
580 T.s = 1;
581
Paul Bakker5121ce52009-01-03 21:22:43 +0000582 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
583 }
584
585 *p++ = '\0';
586 *slen = p - s;
587
588cleanup:
589
Paul Bakker6c591fa2011-05-05 11:49:20 +0000590 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000591
592 return( ret );
593}
594
Paul Bakker335db3f2011-04-25 15:28:35 +0000595#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000596/*
597 * Read X from an opened file
598 */
599int mpi_read_file( mpi *X, int radix, FILE *fin )
600{
Paul Bakkera755ca12011-04-24 09:11:17 +0000601 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000602 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000603 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000604 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000605 * Buffer should have space for (short) label and decimal formatted MPI,
606 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000607 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000608 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000609
610 memset( s, 0, sizeof( s ) );
611 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000612 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000613
614 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000615 if( slen == sizeof( s ) - 2 )
616 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
617
Paul Bakker5121ce52009-01-03 21:22:43 +0000618 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
619 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
620
621 p = s + slen;
622 while( --p >= s )
623 if( mpi_get_digit( &d, radix, *p ) != 0 )
624 break;
625
626 return( mpi_read_string( X, radix, p + 1 ) );
627}
628
629/*
630 * Write X into an opened file (or stdout if fout == NULL)
631 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000632int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000633{
Paul Bakker23986e52011-04-24 08:57:21 +0000634 int ret;
635 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000636 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000637 * Buffer should have space for (short) label and decimal formatted MPI,
638 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000639 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000640 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000641
642 n = sizeof( s );
643 memset( s, 0, n );
644 n -= 2;
645
Paul Bakker23986e52011-04-24 08:57:21 +0000646 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000647
648 if( p == NULL ) p = "";
649
650 plen = strlen( p );
651 slen = strlen( s );
652 s[slen++] = '\r';
653 s[slen++] = '\n';
654
655 if( fout != NULL )
656 {
657 if( fwrite( p, 1, plen, fout ) != plen ||
658 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000659 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000660 }
661 else
Paul Bakker7dc4c442014-02-01 22:50:26 +0100662 polarssl_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000663
664cleanup:
665
666 return( ret );
667}
Paul Bakker335db3f2011-04-25 15:28:35 +0000668#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000669
670/*
671 * Import X from unsigned binary data, big endian
672 */
Paul Bakker23986e52011-04-24 08:57:21 +0000673int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000674{
Paul Bakker23986e52011-04-24 08:57:21 +0000675 int ret;
676 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000677
678 for( n = 0; n < buflen; n++ )
679 if( buf[n] != 0 )
680 break;
681
682 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
683 MPI_CHK( mpi_lset( X, 0 ) );
684
Paul Bakker23986e52011-04-24 08:57:21 +0000685 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000686 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000687
688cleanup:
689
690 return( ret );
691}
692
693/*
694 * Export X into unsigned binary data, big endian
695 */
Paul Bakker23986e52011-04-24 08:57:21 +0000696int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000697{
Paul Bakker23986e52011-04-24 08:57:21 +0000698 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000699
700 n = mpi_size( X );
701
702 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000703 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000704
705 memset( buf, 0, buflen );
706
707 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
708 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
709
710 return( 0 );
711}
712
713/*
714 * Left-shift: X <<= count
715 */
Paul Bakker23986e52011-04-24 08:57:21 +0000716int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000717{
Paul Bakker23986e52011-04-24 08:57:21 +0000718 int ret;
719 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000720 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000721
722 v0 = count / (biL );
723 t1 = count & (biL - 1);
724
725 i = mpi_msb( X ) + count;
726
Paul Bakkerf9688572011-05-05 10:00:45 +0000727 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000728 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
729
730 ret = 0;
731
732 /*
733 * shift by count / limb_size
734 */
735 if( v0 > 0 )
736 {
Paul Bakker23986e52011-04-24 08:57:21 +0000737 for( i = X->n; i > v0; i-- )
738 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000739
Paul Bakker23986e52011-04-24 08:57:21 +0000740 for( ; i > 0; i-- )
741 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000742 }
743
744 /*
745 * shift by count % limb_size
746 */
747 if( t1 > 0 )
748 {
749 for( i = v0; i < X->n; i++ )
750 {
751 r1 = X->p[i] >> (biL - t1);
752 X->p[i] <<= t1;
753 X->p[i] |= r0;
754 r0 = r1;
755 }
756 }
757
758cleanup:
759
760 return( ret );
761}
762
763/*
764 * Right-shift: X >>= count
765 */
Paul Bakker23986e52011-04-24 08:57:21 +0000766int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000767{
Paul Bakker23986e52011-04-24 08:57:21 +0000768 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000769 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000770
771 v0 = count / biL;
772 v1 = count & (biL - 1);
773
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100774 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
775 return mpi_lset( X, 0 );
776
Paul Bakker5121ce52009-01-03 21:22:43 +0000777 /*
778 * shift by count / limb_size
779 */
780 if( v0 > 0 )
781 {
782 for( i = 0; i < X->n - v0; i++ )
783 X->p[i] = X->p[i + v0];
784
785 for( ; i < X->n; i++ )
786 X->p[i] = 0;
787 }
788
789 /*
790 * shift by count % limb_size
791 */
792 if( v1 > 0 )
793 {
Paul Bakker23986e52011-04-24 08:57:21 +0000794 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000795 {
Paul Bakker23986e52011-04-24 08:57:21 +0000796 r1 = X->p[i - 1] << (biL - v1);
797 X->p[i - 1] >>= v1;
798 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000799 r0 = r1;
800 }
801 }
802
803 return( 0 );
804}
805
806/*
807 * Compare unsigned values
808 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000809int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000810{
Paul Bakker23986e52011-04-24 08:57:21 +0000811 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000812
Paul Bakker23986e52011-04-24 08:57:21 +0000813 for( i = X->n; i > 0; i-- )
814 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000815 break;
816
Paul Bakker23986e52011-04-24 08:57:21 +0000817 for( j = Y->n; j > 0; j-- )
818 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000819 break;
820
Paul Bakker23986e52011-04-24 08:57:21 +0000821 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000822 return( 0 );
823
824 if( i > j ) return( 1 );
825 if( j > i ) return( -1 );
826
Paul Bakker23986e52011-04-24 08:57:21 +0000827 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000828 {
Paul Bakker23986e52011-04-24 08:57:21 +0000829 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
830 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000831 }
832
833 return( 0 );
834}
835
836/*
837 * Compare signed values
838 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000839int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000840{
Paul Bakker23986e52011-04-24 08:57:21 +0000841 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000842
Paul Bakker23986e52011-04-24 08:57:21 +0000843 for( i = X->n; i > 0; i-- )
844 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000845 break;
846
Paul Bakker23986e52011-04-24 08:57:21 +0000847 for( j = Y->n; j > 0; j-- )
848 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000849 break;
850
Paul Bakker23986e52011-04-24 08:57:21 +0000851 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000852 return( 0 );
853
854 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000855 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000856
857 if( X->s > 0 && Y->s < 0 ) return( 1 );
858 if( Y->s > 0 && X->s < 0 ) return( -1 );
859
Paul Bakker23986e52011-04-24 08:57:21 +0000860 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000861 {
Paul Bakker23986e52011-04-24 08:57:21 +0000862 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
863 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000864 }
865
866 return( 0 );
867}
868
869/*
870 * Compare signed values
871 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000872int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000873{
874 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000875 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000876
877 *p = ( z < 0 ) ? -z : z;
878 Y.s = ( z < 0 ) ? -1 : 1;
879 Y.n = 1;
880 Y.p = p;
881
882 return( mpi_cmp_mpi( X, &Y ) );
883}
884
885/*
886 * Unsigned addition: X = |A| + |B| (HAC 14.7)
887 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000888int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000889{
Paul Bakker23986e52011-04-24 08:57:21 +0000890 int ret;
891 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000892 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000893
894 if( X == B )
895 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000896 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000897 }
898
899 if( X != A )
900 MPI_CHK( mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200901
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000902 /*
903 * X should always be positive as a result of unsigned additions.
904 */
905 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000906
Paul Bakker23986e52011-04-24 08:57:21 +0000907 for( j = B->n; j > 0; j-- )
908 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000909 break;
910
Paul Bakker23986e52011-04-24 08:57:21 +0000911 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000912
913 o = B->p; p = X->p; c = 0;
914
Paul Bakker23986e52011-04-24 08:57:21 +0000915 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000916 {
917 *p += c; c = ( *p < c );
918 *p += *o; c += ( *p < *o );
919 }
920
921 while( c != 0 )
922 {
923 if( i >= X->n )
924 {
925 MPI_CHK( mpi_grow( X, i + 1 ) );
926 p = X->p + i;
927 }
928
Paul Bakker2d319fd2012-09-16 21:34:26 +0000929 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000930 }
931
932cleanup:
933
934 return( ret );
935}
936
937/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100938 * Helper for mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000939 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000940static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000941{
Paul Bakker23986e52011-04-24 08:57:21 +0000942 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000943 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000944
945 for( i = c = 0; i < n; i++, s++, d++ )
946 {
947 z = ( *d < c ); *d -= c;
948 c = ( *d < *s ) + z; *d -= *s;
949 }
950
951 while( c != 0 )
952 {
953 z = ( *d < c ); *d -= c;
954 c = z; i++; d++;
955 }
956}
957
958/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100959 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000960 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000961int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000962{
963 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000964 int ret;
965 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000966
967 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000968 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000969
Paul Bakker6c591fa2011-05-05 11:49:20 +0000970 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000971
972 if( X == B )
973 {
974 MPI_CHK( mpi_copy( &TB, B ) );
975 B = &TB;
976 }
977
978 if( X != A )
979 MPI_CHK( mpi_copy( X, A ) );
980
Paul Bakker1ef7a532009-06-20 10:50:55 +0000981 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100982 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000983 */
984 X->s = 1;
985
Paul Bakker5121ce52009-01-03 21:22:43 +0000986 ret = 0;
987
Paul Bakker23986e52011-04-24 08:57:21 +0000988 for( n = B->n; n > 0; n-- )
989 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000990 break;
991
Paul Bakker23986e52011-04-24 08:57:21 +0000992 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000993
994cleanup:
995
Paul Bakker6c591fa2011-05-05 11:49:20 +0000996 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000997
998 return( ret );
999}
1000
1001/*
1002 * Signed addition: X = A + B
1003 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001004int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001005{
1006 int ret, s = A->s;
1007
1008 if( A->s * B->s < 0 )
1009 {
1010 if( mpi_cmp_abs( A, B ) >= 0 )
1011 {
1012 MPI_CHK( mpi_sub_abs( X, A, B ) );
1013 X->s = s;
1014 }
1015 else
1016 {
1017 MPI_CHK( mpi_sub_abs( X, B, A ) );
1018 X->s = -s;
1019 }
1020 }
1021 else
1022 {
1023 MPI_CHK( mpi_add_abs( X, A, B ) );
1024 X->s = s;
1025 }
1026
1027cleanup:
1028
1029 return( ret );
1030}
1031
1032/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001033 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001034 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001035int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001036{
1037 int ret, s = A->s;
1038
1039 if( A->s * B->s > 0 )
1040 {
1041 if( mpi_cmp_abs( A, B ) >= 0 )
1042 {
1043 MPI_CHK( mpi_sub_abs( X, A, B ) );
1044 X->s = s;
1045 }
1046 else
1047 {
1048 MPI_CHK( mpi_sub_abs( X, B, A ) );
1049 X->s = -s;
1050 }
1051 }
1052 else
1053 {
1054 MPI_CHK( mpi_add_abs( X, A, B ) );
1055 X->s = s;
1056 }
1057
1058cleanup:
1059
1060 return( ret );
1061}
1062
1063/*
1064 * Signed addition: X = A + b
1065 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001066int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001067{
1068 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001069 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001070
1071 p[0] = ( b < 0 ) ? -b : b;
1072 _B.s = ( b < 0 ) ? -1 : 1;
1073 _B.n = 1;
1074 _B.p = p;
1075
1076 return( mpi_add_mpi( X, A, &_B ) );
1077}
1078
1079/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001080 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001081 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001082int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001083{
1084 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001085 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001086
1087 p[0] = ( b < 0 ) ? -b : b;
1088 _B.s = ( b < 0 ) ? -1 : 1;
1089 _B.n = 1;
1090 _B.p = p;
1091
1092 return( mpi_sub_mpi( X, A, &_B ) );
1093}
1094
1095/*
1096 * Helper for mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001097 */
1098static
1099#if defined(__APPLE__) && defined(__arm__)
1100/*
1101 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1102 * appears to need this to prevent bad ARM code generation at -O3.
1103 */
1104__attribute__ ((noinline))
1105#endif
1106void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001107{
Paul Bakkera755ca12011-04-24 09:11:17 +00001108 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001109
1110#if defined(MULADDC_HUIT)
1111 for( ; i >= 8; i -= 8 )
1112 {
1113 MULADDC_INIT
1114 MULADDC_HUIT
1115 MULADDC_STOP
1116 }
1117
1118 for( ; i > 0; i-- )
1119 {
1120 MULADDC_INIT
1121 MULADDC_CORE
1122 MULADDC_STOP
1123 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001124#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001125 for( ; i >= 16; i -= 16 )
1126 {
1127 MULADDC_INIT
1128 MULADDC_CORE MULADDC_CORE
1129 MULADDC_CORE MULADDC_CORE
1130 MULADDC_CORE MULADDC_CORE
1131 MULADDC_CORE MULADDC_CORE
1132
1133 MULADDC_CORE MULADDC_CORE
1134 MULADDC_CORE MULADDC_CORE
1135 MULADDC_CORE MULADDC_CORE
1136 MULADDC_CORE MULADDC_CORE
1137 MULADDC_STOP
1138 }
1139
1140 for( ; i >= 8; i -= 8 )
1141 {
1142 MULADDC_INIT
1143 MULADDC_CORE MULADDC_CORE
1144 MULADDC_CORE MULADDC_CORE
1145
1146 MULADDC_CORE MULADDC_CORE
1147 MULADDC_CORE MULADDC_CORE
1148 MULADDC_STOP
1149 }
1150
1151 for( ; i > 0; i-- )
1152 {
1153 MULADDC_INIT
1154 MULADDC_CORE
1155 MULADDC_STOP
1156 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001157#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001158
1159 t++;
1160
1161 do {
1162 *d += c; c = ( *d < c ); d++;
1163 }
1164 while( c != 0 );
1165}
1166
1167/*
1168 * Baseline multiplication: X = A * B (HAC 14.12)
1169 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001170int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001171{
Paul Bakker23986e52011-04-24 08:57:21 +00001172 int ret;
1173 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001174 mpi TA, TB;
1175
Paul Bakker6c591fa2011-05-05 11:49:20 +00001176 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001177
1178 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1179 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1180
Paul Bakker23986e52011-04-24 08:57:21 +00001181 for( i = A->n; i > 0; i-- )
1182 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001183 break;
1184
Paul Bakker23986e52011-04-24 08:57:21 +00001185 for( j = B->n; j > 0; j-- )
1186 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001187 break;
1188
Paul Bakker23986e52011-04-24 08:57:21 +00001189 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001190 MPI_CHK( mpi_lset( X, 0 ) );
1191
Paul Bakker23986e52011-04-24 08:57:21 +00001192 for( i++; j > 0; j-- )
1193 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001194
1195 X->s = A->s * B->s;
1196
1197cleanup:
1198
Paul Bakker6c591fa2011-05-05 11:49:20 +00001199 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001200
1201 return( ret );
1202}
1203
1204/*
1205 * Baseline multiplication: X = A * b
1206 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001207int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001208{
1209 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001210 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001211
1212 _B.s = 1;
1213 _B.n = 1;
1214 _B.p = p;
1215 p[0] = b;
1216
1217 return( mpi_mul_mpi( X, A, &_B ) );
1218}
1219
1220/*
Simon Butchere4ed3472015-12-22 15:26:57 +00001221 * Unsigned integer divide - 64bit dividend and 32bit divisor
1222 */
1223static t_uint int_div_int(t_uint u1, t_uint u0, t_uint d, t_uint *r)
1224{
1225#if defined(POLARSSL_HAVE_UDBL)
1226 t_udbl dividend, quotient;
1227#endif
1228
1229 /*
1230 * Check for overflow
1231 */
1232 if(( 0 == d ) || ( u1 >= d ))
1233 {
1234 if (r != NULL) *r = (~0);
1235
1236 return (~0);
1237 }
1238
1239#if defined(POLARSSL_HAVE_UDBL)
1240 dividend = (t_udbl) u1 << biL;
1241 dividend |= (t_udbl) u0;
1242 quotient = dividend / d;
1243 if( quotient > ( (t_udbl) 1 << biL ) - 1 )
1244 quotient = ( (t_udbl) 1 << biL ) - 1;
1245
1246 if( r != NULL )
1247 *r = dividend - (quotient * d);
1248
1249 return (t_uint) quotient;
1250#else
1251 const t_uint radix = 1 << biH;
1252 t_uint d0, d1, q0, q1, rAX, r0, quotient;
1253 t_uint u0_msw, u0_lsw;
1254 int s;
1255
1256 /*
1257 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1258 * Vol. 2 - Seminumerical Algorithms, Knuth
1259 */
1260
1261 /*
1262 * Normalize the divisor, d, and dividend, u0, u1
1263 */
1264 s = int_clz( d );
1265 d = d << s;
1266
1267 u1 = u1 << s;
1268 u1 |= (u0 >> (32 - s)) & ( (-s) >> 31);
1269 u0 = u0 << s;
1270
1271 d1 = d >> biH;
1272 d0 = d & 0xffff;
1273
1274 u0_msw = u0 >> biH;
1275 u0_lsw = u0 & 0xffff;
1276
1277 /*
1278 * Find the first quotient and remainder
1279 */
1280 q1 = u1 / d1;
1281 r0 = u1 - d1 * q1;
1282
1283 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1284 {
1285 q1 -= 1;
1286 r0 += d1;
1287
1288 if ( r0 >= radix ) break;
1289 }
1290
1291 rAX = (u1 * radix) + (u0_msw - q1 * d);
1292 q0 = rAX / d1;
1293 r0 = rAX - q0 * d1;
1294
1295 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1296 {
1297 q0 -= 1;
1298 r0 += d1;
1299
1300 if ( r0 >= radix ) break;
1301 }
1302
1303 if (r != NULL)
1304 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1305
1306 quotient = q1 * radix + q0;
1307
1308 return quotient;
1309#endif
1310}
1311
1312/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001313 * Division by mpi: A = Q * B + R (HAC 14.20)
1314 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001315int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001316{
Paul Bakker23986e52011-04-24 08:57:21 +00001317 int ret;
1318 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001319 mpi X, Y, Z, T1, T2;
1320
1321 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001322 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001323
Paul Bakker6c591fa2011-05-05 11:49:20 +00001324 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1325 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001326
1327 if( mpi_cmp_abs( A, B ) < 0 )
1328 {
1329 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1330 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1331 return( 0 );
1332 }
1333
1334 MPI_CHK( mpi_copy( &X, A ) );
1335 MPI_CHK( mpi_copy( &Y, B ) );
1336 X.s = Y.s = 1;
1337
1338 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1339 MPI_CHK( mpi_lset( &Z, 0 ) );
1340 MPI_CHK( mpi_grow( &T1, 2 ) );
1341 MPI_CHK( mpi_grow( &T2, 3 ) );
1342
1343 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001344 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001345 {
1346 k = biL - 1 - k;
1347 MPI_CHK( mpi_shift_l( &X, k ) );
1348 MPI_CHK( mpi_shift_l( &Y, k ) );
1349 }
1350 else k = 0;
1351
1352 n = X.n - 1;
1353 t = Y.n - 1;
Paul Bakker66d5d072014-06-17 16:39:18 +02001354 MPI_CHK( mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001355
1356 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1357 {
1358 Z.p[n - t]++;
Paul Bakker6ea1a952013-12-31 11:16:03 +01001359 MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001360 }
Paul Bakker66d5d072014-06-17 16:39:18 +02001361 MPI_CHK( mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001362
1363 for( i = n; i > t ; i-- )
1364 {
1365 if( X.p[i] >= Y.p[t] )
1366 Z.p[i - t - 1] = ~0;
1367 else
1368 {
Simon Butchere4ed3472015-12-22 15:26:57 +00001369 Z.p[i - t - 1] = int_div_int( X.p[i], X.p[i - 1], Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001370 }
1371
1372 Z.p[i - t - 1]++;
1373 do
1374 {
1375 Z.p[i - t - 1]--;
1376
1377 MPI_CHK( mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001378 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001379 T1.p[1] = Y.p[t];
1380 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1381
1382 MPI_CHK( mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001383 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1384 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001385 T2.p[2] = X.p[i];
1386 }
1387 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1388
1389 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001390 MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001391 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1392
1393 if( mpi_cmp_int( &X, 0 ) < 0 )
1394 {
1395 MPI_CHK( mpi_copy( &T1, &Y ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001396 MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001397 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1398 Z.p[i - t - 1]--;
1399 }
1400 }
1401
1402 if( Q != NULL )
1403 {
Paul Bakker6ea1a952013-12-31 11:16:03 +01001404 MPI_CHK( mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001405 Q->s = A->s * B->s;
1406 }
1407
1408 if( R != NULL )
1409 {
Paul Bakker6ea1a952013-12-31 11:16:03 +01001410 MPI_CHK( mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001411 X.s = A->s;
Paul Bakker6ea1a952013-12-31 11:16:03 +01001412 MPI_CHK( mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001413
Paul Bakker5121ce52009-01-03 21:22:43 +00001414 if( mpi_cmp_int( R, 0 ) == 0 )
1415 R->s = 1;
1416 }
1417
1418cleanup:
1419
Paul Bakker6c591fa2011-05-05 11:49:20 +00001420 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1421 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001422
1423 return( ret );
1424}
1425
1426/*
1427 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001428 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001429int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001430{
1431 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001432 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001433
1434 p[0] = ( b < 0 ) ? -b : b;
1435 _B.s = ( b < 0 ) ? -1 : 1;
1436 _B.n = 1;
1437 _B.p = p;
1438
1439 return( mpi_div_mpi( Q, R, A, &_B ) );
1440}
1441
1442/*
1443 * Modulo: R = A mod B
1444 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001445int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001446{
1447 int ret;
1448
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001449 if( mpi_cmp_int( B, 0 ) < 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001450 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001451
Paul Bakker5121ce52009-01-03 21:22:43 +00001452 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1453
1454 while( mpi_cmp_int( R, 0 ) < 0 )
1455 MPI_CHK( mpi_add_mpi( R, R, B ) );
1456
1457 while( mpi_cmp_mpi( R, B ) >= 0 )
1458 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1459
1460cleanup:
1461
1462 return( ret );
1463}
1464
1465/*
1466 * Modulo: r = A mod b
1467 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001468int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001469{
Paul Bakker23986e52011-04-24 08:57:21 +00001470 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001471 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001472
1473 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001474 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001475
1476 if( b < 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001477 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001478
1479 /*
1480 * handle trivial cases
1481 */
1482 if( b == 1 )
1483 {
1484 *r = 0;
1485 return( 0 );
1486 }
1487
1488 if( b == 2 )
1489 {
1490 *r = A->p[0] & 1;
1491 return( 0 );
1492 }
1493
1494 /*
1495 * general case
1496 */
Paul Bakker23986e52011-04-24 08:57:21 +00001497 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001498 {
Paul Bakker23986e52011-04-24 08:57:21 +00001499 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001500 y = ( y << biH ) | ( x >> biH );
1501 z = y / b;
1502 y -= z * b;
1503
1504 x <<= biH;
1505 y = ( y << biH ) | ( x >> biH );
1506 z = y / b;
1507 y -= z * b;
1508 }
1509
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001510 /*
1511 * If A is negative, then the current y represents a negative value.
1512 * Flipping it to the positive side.
1513 */
1514 if( A->s < 0 && y != 0 )
1515 y = b - y;
1516
Paul Bakker5121ce52009-01-03 21:22:43 +00001517 *r = y;
1518
1519 return( 0 );
1520}
1521
1522/*
1523 * Fast Montgomery initialization (thanks to Tom St Denis)
1524 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001525static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001526{
Paul Bakkera755ca12011-04-24 09:11:17 +00001527 t_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001528 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001529
1530 x = m0;
1531 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001532
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001533 for( i = biL; i >= 8; i /= 2 )
1534 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001535
1536 *mm = ~x + 1;
1537}
1538
1539/*
1540 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1541 */
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02001542static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm,
1543 const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001544{
Paul Bakker23986e52011-04-24 08:57:21 +00001545 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001546 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001547
1548 memset( T->p, 0, T->n * ciL );
1549
1550 d = T->p;
1551 n = N->n;
1552 m = ( B->n < n ) ? B->n : n;
1553
1554 for( i = 0; i < n; i++ )
1555 {
1556 /*
1557 * T = (T + u0*B + u1*N) / 2^biL
1558 */
1559 u0 = A->p[i];
1560 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1561
1562 mpi_mul_hlp( m, B->p, d, u0 );
1563 mpi_mul_hlp( n, N->p, d, u1 );
1564
1565 *d++ = u0; d[n + 1] = 0;
1566 }
1567
Paul Bakker66d5d072014-06-17 16:39:18 +02001568 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001569
1570 if( mpi_cmp_abs( A, N ) >= 0 )
1571 mpi_sub_hlp( n, N->p, A->p );
1572 else
1573 /* prevent timing attacks */
1574 mpi_sub_hlp( n, A->p, T->p );
1575}
1576
1577/*
1578 * Montgomery reduction: A = A * R^-1 mod N
1579 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001580static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001581{
Paul Bakkera755ca12011-04-24 09:11:17 +00001582 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001583 mpi U;
1584
Paul Bakker8ddb6452013-02-27 14:56:33 +01001585 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001586 U.p = &z;
1587
1588 mpi_montmul( A, &U, N, mm, T );
1589}
1590
1591/*
1592 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1593 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001594int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001595{
Paul Bakker23986e52011-04-24 08:57:21 +00001596 int ret;
1597 size_t wbits, wsize, one = 1;
1598 size_t i, j, nblimbs;
1599 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001600 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001601 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1602 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001603
1604 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001605 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001606
Paul Bakkerf6198c12012-05-16 08:02:29 +00001607 if( mpi_cmp_int( E, 0 ) < 0 )
1608 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1609
1610 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001611 * Init temps and window size
1612 */
1613 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001614 mpi_init( &RR ); mpi_init( &T );
Manuel Pégourié-Gonnardfd6a1912014-01-18 19:05:23 +01001615 mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001616 memset( W, 0, sizeof( W ) );
1617
1618 i = mpi_msb( E );
1619
1620 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1621 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1622
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001623 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1624 wsize = POLARSSL_MPI_WINDOW_SIZE;
1625
Paul Bakker5121ce52009-01-03 21:22:43 +00001626 j = N->n + 1;
1627 MPI_CHK( mpi_grow( X, j ) );
1628 MPI_CHK( mpi_grow( &W[1], j ) );
1629 MPI_CHK( mpi_grow( &T, j * 2 ) );
1630
1631 /*
Paul Bakker50546922012-05-19 08:40:49 +00001632 * Compensate for negative A (and correct at the end)
1633 */
1634 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001635 if( neg )
1636 {
1637 MPI_CHK( mpi_copy( &Apos, A ) );
1638 Apos.s = 1;
1639 A = &Apos;
1640 }
1641
1642 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001643 * If 1st call, pre-compute R^2 mod N
1644 */
1645 if( _RR == NULL || _RR->p == NULL )
1646 {
1647 MPI_CHK( mpi_lset( &RR, 1 ) );
1648 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1649 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1650
1651 if( _RR != NULL )
1652 memcpy( _RR, &RR, sizeof( mpi ) );
1653 }
1654 else
1655 memcpy( &RR, _RR, sizeof( mpi ) );
1656
1657 /*
1658 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1659 */
1660 if( mpi_cmp_mpi( A, N ) >= 0 )
Paul Bakkerc2024f42014-01-23 20:38:35 +01001661 MPI_CHK( mpi_mod_mpi( &W[1], A, N ) );
1662 else
1663 MPI_CHK( mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001664
1665 mpi_montmul( &W[1], &RR, N, mm, &T );
1666
1667 /*
1668 * X = R^2 * R^-1 mod N = R mod N
1669 */
1670 MPI_CHK( mpi_copy( X, &RR ) );
1671 mpi_montred( X, N, mm, &T );
1672
1673 if( wsize > 1 )
1674 {
1675 /*
1676 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1677 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001678 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001679
1680 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1681 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1682
1683 for( i = 0; i < wsize - 1; i++ )
1684 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001685
Paul Bakker5121ce52009-01-03 21:22:43 +00001686 /*
1687 * W[i] = W[i - 1] * W[1]
1688 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001689 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001690 {
1691 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1692 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1693
1694 mpi_montmul( &W[i], &W[1], N, mm, &T );
1695 }
1696 }
1697
1698 nblimbs = E->n;
1699 bufsize = 0;
1700 nbits = 0;
1701 wbits = 0;
1702 state = 0;
1703
1704 while( 1 )
1705 {
1706 if( bufsize == 0 )
1707 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001708 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001709 break;
1710
Paul Bakker0d7702c2013-10-29 16:18:35 +01001711 nblimbs--;
1712
Paul Bakkera755ca12011-04-24 09:11:17 +00001713 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001714 }
1715
1716 bufsize--;
1717
1718 ei = (E->p[nblimbs] >> bufsize) & 1;
1719
1720 /*
1721 * skip leading 0s
1722 */
1723 if( ei == 0 && state == 0 )
1724 continue;
1725
1726 if( ei == 0 && state == 1 )
1727 {
1728 /*
1729 * out of window, square X
1730 */
1731 mpi_montmul( X, X, N, mm, &T );
1732 continue;
1733 }
1734
1735 /*
1736 * add ei to current window
1737 */
1738 state = 2;
1739
1740 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001741 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001742
1743 if( nbits == wsize )
1744 {
1745 /*
1746 * X = X^wsize R^-1 mod N
1747 */
1748 for( i = 0; i < wsize; i++ )
1749 mpi_montmul( X, X, N, mm, &T );
1750
1751 /*
1752 * X = X * W[wbits] R^-1 mod N
1753 */
1754 mpi_montmul( X, &W[wbits], N, mm, &T );
1755
1756 state--;
1757 nbits = 0;
1758 wbits = 0;
1759 }
1760 }
1761
1762 /*
1763 * process the remaining bits
1764 */
1765 for( i = 0; i < nbits; i++ )
1766 {
1767 mpi_montmul( X, X, N, mm, &T );
1768
1769 wbits <<= 1;
1770
Paul Bakker66d5d072014-06-17 16:39:18 +02001771 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001772 mpi_montmul( X, &W[1], N, mm, &T );
1773 }
1774
1775 /*
1776 * X = A^E * R * R^-1 mod N = A^E mod N
1777 */
1778 mpi_montred( X, N, mm, &T );
1779
Paul Bakkerf6198c12012-05-16 08:02:29 +00001780 if( neg )
1781 {
1782 X->s = -1;
Paul Bakkerc2024f42014-01-23 20:38:35 +01001783 MPI_CHK( mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001784 }
1785
Paul Bakker5121ce52009-01-03 21:22:43 +00001786cleanup:
1787
Paul Bakker66d5d072014-06-17 16:39:18 +02001788 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001789 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001790
Paul Bakkerf6198c12012-05-16 08:02:29 +00001791 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001792
Paul Bakker75a28602014-03-31 12:08:17 +02001793 if( _RR == NULL || _RR->p == NULL )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001794 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001795
1796 return( ret );
1797}
1798
Paul Bakker5121ce52009-01-03 21:22:43 +00001799/*
1800 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1801 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001802int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001803{
Paul Bakker23986e52011-04-24 08:57:21 +00001804 int ret;
1805 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001806 mpi TG, TA, TB;
1807
Paul Bakker6c591fa2011-05-05 11:49:20 +00001808 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001809
Paul Bakker5121ce52009-01-03 21:22:43 +00001810 MPI_CHK( mpi_copy( &TA, A ) );
1811 MPI_CHK( mpi_copy( &TB, B ) );
1812
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001813 lz = mpi_lsb( &TA );
1814 lzt = mpi_lsb( &TB );
1815
Paul Bakker66d5d072014-06-17 16:39:18 +02001816 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001817 lz = lzt;
1818
1819 MPI_CHK( mpi_shift_r( &TA, lz ) );
1820 MPI_CHK( mpi_shift_r( &TB, lz ) );
1821
Paul Bakker5121ce52009-01-03 21:22:43 +00001822 TA.s = TB.s = 1;
1823
1824 while( mpi_cmp_int( &TA, 0 ) != 0 )
1825 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001826 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1827 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001828
1829 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1830 {
1831 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1832 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1833 }
1834 else
1835 {
1836 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1837 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1838 }
1839 }
1840
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001841 MPI_CHK( mpi_shift_l( &TB, lz ) );
1842 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001843
1844cleanup:
1845
Paul Bakker6c591fa2011-05-05 11:49:20 +00001846 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001847
1848 return( ret );
1849}
1850
Paul Bakker33dc46b2014-04-30 16:11:39 +02001851/*
1852 * Fill X with size bytes of random.
1853 *
1854 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001855 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001856 * deterministic, eg for tests).
1857 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001858int mpi_fill_random( mpi *X, size_t size,
1859 int (*f_rng)(void *, unsigned char *, size_t),
1860 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001861{
Paul Bakker23986e52011-04-24 08:57:21 +00001862 int ret;
Paul Bakker33dc46b2014-04-30 16:11:39 +02001863 unsigned char buf[POLARSSL_MPI_MAX_SIZE];
1864
1865 if( size > POLARSSL_MPI_MAX_SIZE )
1866 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001867
Paul Bakker33dc46b2014-04-30 16:11:39 +02001868 MPI_CHK( f_rng( p_rng, buf, size ) );
1869 MPI_CHK( mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001870
1871cleanup:
1872 return( ret );
1873}
1874
Paul Bakker5121ce52009-01-03 21:22:43 +00001875/*
1876 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1877 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001878int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001879{
1880 int ret;
1881 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1882
1883 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001884 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001885
Paul Bakker6c591fa2011-05-05 11:49:20 +00001886 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1887 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1888 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001889
1890 MPI_CHK( mpi_gcd( &G, A, N ) );
1891
1892 if( mpi_cmp_int( &G, 1 ) != 0 )
1893 {
Paul Bakker40e46942009-01-03 21:51:57 +00001894 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001895 goto cleanup;
1896 }
1897
1898 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1899 MPI_CHK( mpi_copy( &TU, &TA ) );
1900 MPI_CHK( mpi_copy( &TB, N ) );
1901 MPI_CHK( mpi_copy( &TV, N ) );
1902
1903 MPI_CHK( mpi_lset( &U1, 1 ) );
1904 MPI_CHK( mpi_lset( &U2, 0 ) );
1905 MPI_CHK( mpi_lset( &V1, 0 ) );
1906 MPI_CHK( mpi_lset( &V2, 1 ) );
1907
1908 do
1909 {
1910 while( ( TU.p[0] & 1 ) == 0 )
1911 {
1912 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1913
1914 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1915 {
1916 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1917 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1918 }
1919
1920 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1921 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1922 }
1923
1924 while( ( TV.p[0] & 1 ) == 0 )
1925 {
1926 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1927
1928 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1929 {
1930 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1931 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1932 }
1933
1934 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1935 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1936 }
1937
1938 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1939 {
1940 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1941 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1942 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1943 }
1944 else
1945 {
1946 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1947 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1948 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1949 }
1950 }
1951 while( mpi_cmp_int( &TU, 0 ) != 0 );
1952
1953 while( mpi_cmp_int( &V1, 0 ) < 0 )
1954 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1955
1956 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1957 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1958
1959 MPI_CHK( mpi_copy( X, &V1 ) );
1960
1961cleanup:
1962
Paul Bakker6c591fa2011-05-05 11:49:20 +00001963 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1964 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1965 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001966
1967 return( ret );
1968}
1969
Paul Bakkerd9374b02012-11-02 11:02:58 +00001970#if defined(POLARSSL_GENPRIME)
1971
Paul Bakker5121ce52009-01-03 21:22:43 +00001972static const int small_prime[] =
1973{
1974 3, 5, 7, 11, 13, 17, 19, 23,
1975 29, 31, 37, 41, 43, 47, 53, 59,
1976 61, 67, 71, 73, 79, 83, 89, 97,
1977 101, 103, 107, 109, 113, 127, 131, 137,
1978 139, 149, 151, 157, 163, 167, 173, 179,
1979 181, 191, 193, 197, 199, 211, 223, 227,
1980 229, 233, 239, 241, 251, 257, 263, 269,
1981 271, 277, 281, 283, 293, 307, 311, 313,
1982 317, 331, 337, 347, 349, 353, 359, 367,
1983 373, 379, 383, 389, 397, 401, 409, 419,
1984 421, 431, 433, 439, 443, 449, 457, 461,
1985 463, 467, 479, 487, 491, 499, 503, 509,
1986 521, 523, 541, 547, 557, 563, 569, 571,
1987 577, 587, 593, 599, 601, 607, 613, 617,
1988 619, 631, 641, 643, 647, 653, 659, 661,
1989 673, 677, 683, 691, 701, 709, 719, 727,
1990 733, 739, 743, 751, 757, 761, 769, 773,
1991 787, 797, 809, 811, 821, 823, 827, 829,
1992 839, 853, 857, 859, 863, 877, 881, 883,
1993 887, 907, 911, 919, 929, 937, 941, 947,
1994 953, 967, 971, 977, 983, 991, 997, -103
1995};
1996
1997/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001998 * Small divisors test (X must be positive)
1999 *
2000 * Return values:
2001 * 0: no small factor (possible prime, more tests needed)
2002 * 1: certain prime
2003 * POLARSSL_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2004 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002005 */
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002006static int mpi_check_small_factors( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002007{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002008 int ret = 0;
2009 size_t i;
2010 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002011
Paul Bakker5121ce52009-01-03 21:22:43 +00002012 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002013 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002014
2015 for( i = 0; small_prime[i] > 0; i++ )
2016 {
Paul Bakker5121ce52009-01-03 21:22:43 +00002017 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002018 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002019
2020 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
2021
2022 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002023 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002024 }
2025
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002026cleanup:
2027 return( ret );
2028}
2029
2030/*
2031 * Miller-Rabin pseudo-primality test (HAC 4.24)
2032 */
2033static int mpi_miller_rabin( const mpi *X,
2034 int (*f_rng)(void *, unsigned char *, size_t),
2035 void *p_rng )
2036{
Pascal Junodb99183d2015-03-11 16:49:45 +01002037 int ret, count;
2038 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002039 mpi W, R, T, A, RR;
2040
2041 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
2042 mpi_init( &RR );
2043
Paul Bakker5121ce52009-01-03 21:22:43 +00002044 /*
2045 * W = |X| - 1
2046 * R = W >> lsb( W )
2047 */
Paul Bakker5121ce52009-01-03 21:22:43 +00002048 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00002049 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00002050 MPI_CHK( mpi_copy( &R, &W ) );
2051 MPI_CHK( mpi_shift_r( &R, s ) );
2052
2053 i = mpi_msb( X );
2054 /*
2055 * HAC, table 4.4
2056 */
2057 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2058 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2059 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2060
2061 for( i = 0; i < n; i++ )
2062 {
2063 /*
2064 * pick a random A, 1 < A < |X| - 1
2065 */
Paul Bakker5121ce52009-01-03 21:22:43 +00002066
Pascal Junodb99183d2015-03-11 16:49:45 +01002067 count = 0;
2068 do {
2069 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
2070
2071 j = mpi_msb( &A );
2072 k = mpi_msb( &W );
2073 if (j > k) {
2074 MPI_CHK( mpi_shift_r( &A, j - k ) );
2075 }
2076
2077 if (count++ > 30) {
2078 return POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
2079 }
2080
2081 } while ( (mpi_cmp_mpi( &A, &W ) >= 0) ||
2082 (mpi_cmp_int( &A, 1 ) <= 0) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002083
2084 /*
2085 * A = A^R mod |X|
2086 */
2087 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
2088
2089 if( mpi_cmp_mpi( &A, &W ) == 0 ||
2090 mpi_cmp_int( &A, 1 ) == 0 )
2091 continue;
2092
2093 j = 1;
2094 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
2095 {
2096 /*
2097 * A = A * A mod |X|
2098 */
2099 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
2100 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
2101
2102 if( mpi_cmp_int( &A, 1 ) == 0 )
2103 break;
2104
2105 j++;
2106 }
2107
2108 /*
2109 * not prime if A != |X| - 1 or A == 1
2110 */
2111 if( mpi_cmp_mpi( &A, &W ) != 0 ||
2112 mpi_cmp_int( &A, 1 ) == 0 )
2113 {
Paul Bakker40e46942009-01-03 21:51:57 +00002114 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002115 break;
2116 }
2117 }
2118
2119cleanup:
Paul Bakker6c591fa2011-05-05 11:49:20 +00002120 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
2121 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002122
2123 return( ret );
2124}
2125
2126/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002127 * Pseudo-primality test: small factors, then Miller-Rabin
2128 */
Paul Bakker45f457d2013-11-25 14:26:52 +01002129int mpi_is_prime( mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002130 int (*f_rng)(void *, unsigned char *, size_t),
2131 void *p_rng )
2132{
2133 int ret;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002134 mpi XX;
2135
2136 XX.s = 1;
2137 XX.n = X->n;
2138 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002139
2140 if( mpi_cmp_int( &XX, 0 ) == 0 ||
2141 mpi_cmp_int( &XX, 1 ) == 0 )
2142 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
2143
2144 if( mpi_cmp_int( &XX, 2 ) == 0 )
2145 return( 0 );
2146
2147 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2148 {
2149 if( ret == 1 )
2150 return( 0 );
2151
2152 return( ret );
2153 }
2154
2155 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2156}
2157
2158/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002159 * Prime number generation
2160 */
Paul Bakker23986e52011-04-24 08:57:21 +00002161int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002162 int (*f_rng)(void *, unsigned char *, size_t),
2163 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002164{
Paul Bakker23986e52011-04-24 08:57:21 +00002165 int ret;
2166 size_t k, n;
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002167 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002168 mpi Y;
2169
Paul Bakkerfe3256e2011-11-25 12:11:43 +00002170 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00002171 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002172
Paul Bakker6c591fa2011-05-05 11:49:20 +00002173 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002174
2175 n = BITS_TO_LIMBS( nbits );
2176
Paul Bakker901c6562012-04-20 13:25:38 +00002177 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002178
2179 k = mpi_msb( X );
Pascal Junodb99183d2015-03-11 16:49:45 +01002180 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002181
Pascal Junodb99183d2015-03-11 16:49:45 +01002182 mpi_set_bit( X, nbits-1, 1 );
2183
2184 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002185
2186 if( dh_flag == 0 )
2187 {
2188 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
2189 {
Paul Bakker40e46942009-01-03 21:51:57 +00002190 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002191 goto cleanup;
2192
2193 MPI_CHK( mpi_add_int( X, X, 2 ) );
2194 }
2195 }
2196 else
2197 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002198 /*
2199 * An necessary condition for Y and X = 2Y + 1 to be prime
2200 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2201 * Make sure it is satisfied, while keeping X = 3 mod 4
2202 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002203
2204 X->p[0] |= 2;
2205
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002206 MPI_CHK( mpi_mod_int( &r, X, 3 ) );
2207 if( r == 0 )
2208 MPI_CHK( mpi_add_int( X, X, 8 ) );
2209 else if( r == 1 )
2210 MPI_CHK( mpi_add_int( X, X, 4 ) );
2211
2212 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2213 MPI_CHK( mpi_copy( &Y, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002214 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2215
2216 while( 1 )
2217 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002218 /*
2219 * First, check small factors for X and Y
2220 * before doing Miller-Rabin on any of them
2221 */
2222 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2223 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2224 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2225 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002226 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002227 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002228 }
2229
Paul Bakker40e46942009-01-03 21:51:57 +00002230 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002231 goto cleanup;
2232
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002233 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002234 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002235 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2236 * so up Y by 6 and X by 12.
2237 */
2238 MPI_CHK( mpi_add_int( X, X, 12 ) );
2239 MPI_CHK( mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002240 }
2241 }
2242
2243cleanup:
2244
Paul Bakker6c591fa2011-05-05 11:49:20 +00002245 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002246
2247 return( ret );
2248}
2249
Manuel Pégourié-Gonnarddf0142b2013-08-22 18:29:07 +02002250#endif /* POLARSSL_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002251
Paul Bakker40e46942009-01-03 21:51:57 +00002252#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002253
Paul Bakker23986e52011-04-24 08:57:21 +00002254#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002255
2256static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2257{
2258 { 693, 609, 21 },
2259 { 1764, 868, 28 },
2260 { 768454923, 542167814, 1 }
2261};
2262
Paul Bakker5121ce52009-01-03 21:22:43 +00002263/*
2264 * Checkup routine
2265 */
2266int mpi_self_test( int verbose )
2267{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002268 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002269 mpi A, E, N, X, Y, U, V;
2270
Paul Bakker6c591fa2011-05-05 11:49:20 +00002271 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2272 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002273
2274 MPI_CHK( mpi_read_string( &A, 16,
2275 "EFE021C2645FD1DC586E69184AF4A31E" \
2276 "D5F53E93B5F123FA41680867BA110131" \
2277 "944FE7952E2517337780CB0DB80E61AA" \
2278 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2279
2280 MPI_CHK( mpi_read_string( &E, 16,
2281 "B2E7EFD37075B9F03FF989C7C5051C20" \
2282 "34D2A323810251127E7BF8625A4F49A5" \
2283 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2284 "5B5C25763222FEFCCFC38B832366C29E" ) );
2285
2286 MPI_CHK( mpi_read_string( &N, 16,
2287 "0066A198186C18C10B2F5ED9B522752A" \
2288 "9830B69916E535C8F047518A889A43A5" \
2289 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2290
2291 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2292
2293 MPI_CHK( mpi_read_string( &U, 16,
2294 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2295 "9E857EA95A03512E2BAE7391688D264A" \
2296 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2297 "8001B72E848A38CAE1C65F78E56ABDEF" \
2298 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2299 "ECF677152EF804370C1A305CAF3B5BF1" \
2300 "30879B56C61DE584A0F53A2447A51E" ) );
2301
2302 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002303 polarssl_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002304
2305 if( mpi_cmp_mpi( &X, &U ) != 0 )
2306 {
2307 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002308 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002309
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002310 ret = 1;
2311 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002312 }
2313
2314 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002315 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002316
2317 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2318
2319 MPI_CHK( mpi_read_string( &U, 16,
2320 "256567336059E52CAE22925474705F39A94" ) );
2321
2322 MPI_CHK( mpi_read_string( &V, 16,
2323 "6613F26162223DF488E9CD48CC132C7A" \
2324 "0AC93C701B001B092E4E5B9F73BCD27B" \
2325 "9EE50D0657C77F374E903CDFA4C642" ) );
2326
2327 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002328 polarssl_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002329
2330 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2331 mpi_cmp_mpi( &Y, &V ) != 0 )
2332 {
2333 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002334 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002335
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002336 ret = 1;
2337 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002338 }
2339
2340 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002341 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002342
2343 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2344
2345 MPI_CHK( mpi_read_string( &U, 16,
2346 "36E139AEA55215609D2816998ED020BB" \
2347 "BD96C37890F65171D948E9BC7CBAA4D9" \
2348 "325D24D6A3C12710F10A09FA08AB87" ) );
2349
2350 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002351 polarssl_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002352
2353 if( mpi_cmp_mpi( &X, &U ) != 0 )
2354 {
2355 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002356 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002357
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002358 ret = 1;
2359 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002360 }
2361
2362 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002363 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002364
2365 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2366
2367 MPI_CHK( mpi_read_string( &U, 16,
2368 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2369 "C3DBA76456363A10869622EAC2DD84EC" \
2370 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2371
2372 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002373 polarssl_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002374
2375 if( mpi_cmp_mpi( &X, &U ) != 0 )
2376 {
2377 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002378 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002379
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002380 ret = 1;
2381 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002382 }
2383
2384 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002385 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002386
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002387 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002388 polarssl_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002389
Paul Bakker66d5d072014-06-17 16:39:18 +02002390 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002391 {
2392 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002393 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002394
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002395 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002396
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002397 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2398 {
2399 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002400 polarssl_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002401
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002402 ret = 1;
2403 goto cleanup;
2404 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002405 }
2406
2407 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002408 polarssl_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002409
Paul Bakker5121ce52009-01-03 21:22:43 +00002410cleanup:
2411
2412 if( ret != 0 && verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002413 polarssl_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002414
Paul Bakker6c591fa2011-05-05 11:49:20 +00002415 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2416 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002417
2418 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002419 polarssl_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002420
2421 return( ret );
2422}
2423
Paul Bakker9af723c2014-05-01 13:03:14 +02002424#endif /* POLARSSL_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002425
Paul Bakker9af723c2014-05-01 13:03:14 +02002426#endif /* POLARSSL_BIGNUM_C */