blob: 15457ab794c19c3b2839762f3b5b1b879b5eec14 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Paul Bakker530927b2015-02-13 14:24:10 +01004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Paul Bakkerb96f1542010-07-18 20:36:00 +00005 *
Manuel Pégourié-Gonnarde12abf92015-01-28 17:13:45 +00006 * This file is part of mbed TLS (https://polarssl.org)
Paul Bakkere0ccd0a2009-01-04 16:27:10 +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 Butcher15f0bbe2015-12-22 15:26:57 +000022
Paul Bakker5121ce52009-01-03 21:22:43 +000023/*
Simon Butcher15f0bbe2015-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 Butcher15f0bbe2015-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
Paul Bakker40e46942009-01-03 21:51:57 +000039#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000040
Paul Bakker40e46942009-01-03 21:51:57 +000041#if defined(POLARSSL_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000042
Paul Bakker40e46942009-01-03 21:51:57 +000043#include "polarssl/bignum.h"
44#include "polarssl/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Paul Bakker5121ce52009-01-03 21:22:43 +000046#include <stdlib.h>
Paul Bakker5121ce52009-01-03 21:22:43 +000047
Paul Bakker312da332014-06-13 17:20:13 +020048/* Implementation that should never be optimized out by the compiler */
49static void polarssl_zeroize( void *v, size_t n ) {
50 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
51}
52
Paul Bakkerf9688572011-05-05 10:00:45 +000053#define ciL (sizeof(t_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000054#define biL (ciL << 3) /* bits in limb */
55#define biH (ciL << 2) /* half limb size */
56
Manuel Pégourié-Gonnard42571dd2015-10-05 15:23:11 +010057#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
58
Paul Bakker5121ce52009-01-03 21:22:43 +000059/*
60 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard9b753052015-09-28 13:48:04 +020061 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000062 */
Manuel Pégourié-Gonnard9b753052015-09-28 13:48:04 +020063#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
64#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000065
66/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000067 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000068 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000069void mpi_init( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000070{
Paul Bakker6c591fa2011-05-05 11:49:20 +000071 if( X == NULL )
72 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000073
Paul Bakker6c591fa2011-05-05 11:49:20 +000074 X->s = 1;
75 X->n = 0;
76 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000077}
78
79/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000080 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000081 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000082void mpi_free( 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 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +000088 {
Paul Bakker312da332014-06-13 17:20:13 +020089 polarssl_zeroize( X->p, X->n * ciL );
Paul Bakker6c591fa2011-05-05 11:49:20 +000090 free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +000091 }
92
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 X->s = 1;
94 X->n = 0;
95 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000096}
97
98/*
99 * Enlarge to the specified number of limbs
100 */
Paul Bakker23986e52011-04-24 08:57:21 +0000101int mpi_grow( mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102{
Paul Bakkera755ca12011-04-24 09:11:17 +0000103 t_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000104
Paul Bakkerf9688572011-05-05 10:00:45 +0000105 if( nblimbs > POLARSSL_MPI_MAX_LIMBS )
Paul Bakker69e095c2011-12-10 21:55:01 +0000106 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000107
Paul Bakker5121ce52009-01-03 21:22:43 +0000108 if( X->n < nblimbs )
109 {
Paul Bakkera755ca12011-04-24 09:11:17 +0000110 if( ( p = (t_uint *) malloc( nblimbs * ciL ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000111 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000112
113 memset( p, 0, nblimbs * ciL );
114
115 if( X->p != NULL )
116 {
117 memcpy( p, X->p, X->n * ciL );
Paul Bakker312da332014-06-13 17:20:13 +0200118 polarssl_zeroize( X->p, X->n * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000119 free( X->p );
120 }
121
122 X->n = nblimbs;
123 X->p = p;
124 }
125
126 return( 0 );
127}
128
129/*
130 * Copy the contents of Y into X
131 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000132int mpi_copy( mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000133{
Paul Bakker23986e52011-04-24 08:57:21 +0000134 int ret;
135 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000136
137 if( X == Y )
138 return( 0 );
139
140 for( i = Y->n - 1; i > 0; i-- )
141 if( Y->p[i] != 0 )
142 break;
143 i++;
144
145 X->s = Y->s;
146
147 MPI_CHK( mpi_grow( X, i ) );
148
149 memset( X->p, 0, X->n * ciL );
150 memcpy( X->p, Y->p, i * ciL );
151
152cleanup:
153
154 return( ret );
155}
156
157/*
158 * Swap the contents of X and Y
159 */
160void mpi_swap( mpi *X, mpi *Y )
161{
162 mpi T;
163
164 memcpy( &T, X, sizeof( mpi ) );
165 memcpy( X, Y, sizeof( mpi ) );
166 memcpy( Y, &T, sizeof( mpi ) );
167}
168
169/*
170 * Set value from integer
171 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000172int mpi_lset( mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000173{
174 int ret;
175
176 MPI_CHK( mpi_grow( X, 1 ) );
177 memset( X->p, 0, X->n * ciL );
178
179 X->p[0] = ( z < 0 ) ? -z : z;
180 X->s = ( z < 0 ) ? -1 : 1;
181
182cleanup:
183
184 return( ret );
185}
186
187/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000188 * Get a specific bit
189 */
Paul Bakker6b906e52012-05-08 12:01:43 +0000190int mpi_get_bit( const mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000191{
192 if( X->n * biL <= pos )
193 return( 0 );
194
195 return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
196}
197
198/*
199 * Set a bit to a specific value of 0 or 1
200 */
201int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
202{
203 int ret = 0;
204 size_t off = pos / biL;
205 size_t idx = pos % biL;
206
207 if( val != 0 && val != 1 )
208 return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
209
210 if( X->n * biL <= pos )
211 {
212 if( val == 0 )
213 return ( 0 );
214
215 MPI_CHK( mpi_grow( X, off + 1 ) );
216 }
217
218 X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
219
220cleanup:
221
222 return( ret );
223}
224
225/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000226 * Return the number of least significant bits
227 */
Paul Bakker23986e52011-04-24 08:57:21 +0000228size_t mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000229{
Paul Bakker23986e52011-04-24 08:57:21 +0000230 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000231
232 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000233 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000234 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
235 return( count );
236
237 return( 0 );
238}
239
240/*
Simon Butcher15f0bbe2015-12-22 15:26:57 +0000241 * Count leading zero bits in a given integer
242 */
243static size_t int_clz( const t_uint x )
244{
245 size_t j;
246 t_uint mask = (t_uint) 1 << (biL - 1);
247
248 for( j = 0; j < biL; j++ )
249 {
250 if( x & mask ) break;
251
252 mask >>= 1;
253 }
254
255 return j;
256}
257
258/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000259 * Return the number of most significant bits
260 */
Paul Bakker23986e52011-04-24 08:57:21 +0000261size_t mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000262{
Paul Bakker23986e52011-04-24 08:57:21 +0000263 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000264
265 for( i = X->n - 1; i > 0; i-- )
266 if( X->p[i] != 0 )
267 break;
268
Simon Butcher15f0bbe2015-12-22 15:26:57 +0000269 j = biL - int_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000270
Paul Bakker23986e52011-04-24 08:57:21 +0000271 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000272}
273
274/*
275 * Return the total size in bytes
276 */
Paul Bakker23986e52011-04-24 08:57:21 +0000277size_t mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000278{
279 return( ( mpi_msb( X ) + 7 ) >> 3 );
280}
281
282/*
283 * Convert an ASCII character to digit value
284 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000285static int mpi_get_digit( t_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000286{
287 *d = 255;
288
289 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
290 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
291 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
292
Paul Bakkera755ca12011-04-24 09:11:17 +0000293 if( *d >= (t_uint) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000294 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000295
296 return( 0 );
297}
298
299/*
300 * Import from an ASCII string
301 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000302int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000303{
Paul Bakker23986e52011-04-24 08:57:21 +0000304 int ret;
305 size_t i, j, slen, n;
Paul Bakkera755ca12011-04-24 09:11:17 +0000306 t_uint d;
Paul Bakker5121ce52009-01-03 21:22:43 +0000307 mpi T;
308
309 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000310 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000311
Paul Bakker6c591fa2011-05-05 11:49:20 +0000312 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000313
Paul Bakkerff60ee62010-03-16 21:09:09 +0000314 slen = strlen( s );
315
Paul Bakker5121ce52009-01-03 21:22:43 +0000316 if( radix == 16 )
317 {
Manuel Pégourié-Gonnard42571dd2015-10-05 15:23:11 +0100318 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard9b753052015-09-28 13:48:04 +0200319 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
320
Paul Bakkerff60ee62010-03-16 21:09:09 +0000321 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000322
323 MPI_CHK( mpi_grow( X, n ) );
324 MPI_CHK( mpi_lset( X, 0 ) );
325
Paul Bakker23986e52011-04-24 08:57:21 +0000326 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000327 {
Paul Bakker23986e52011-04-24 08:57:21 +0000328 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000329 {
330 X->s = -1;
331 break;
332 }
333
Paul Bakker23986e52011-04-24 08:57:21 +0000334 MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000335 X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
336 }
337 }
338 else
339 {
340 MPI_CHK( mpi_lset( X, 0 ) );
341
Paul Bakkerff60ee62010-03-16 21:09:09 +0000342 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000343 {
344 if( i == 0 && s[i] == '-' )
345 {
346 X->s = -1;
347 continue;
348 }
349
350 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
351 MPI_CHK( mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000352
353 if( X->s == 1 )
354 {
355 MPI_CHK( mpi_add_int( X, &T, d ) );
356 }
357 else
358 {
359 MPI_CHK( mpi_sub_int( X, &T, d ) );
360 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000361 }
362 }
363
364cleanup:
365
Paul Bakker6c591fa2011-05-05 11:49:20 +0000366 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000367
368 return( ret );
369}
370
371/*
372 * Helper to write the digits high-order first
373 */
374static int mpi_write_hlp( mpi *X, int radix, char **p )
375{
376 int ret;
Paul Bakkera755ca12011-04-24 09:11:17 +0000377 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000378
379 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000380 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000381
382 MPI_CHK( mpi_mod_int( &r, X, radix ) );
383 MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
384
385 if( mpi_cmp_int( X, 0 ) != 0 )
386 MPI_CHK( mpi_write_hlp( X, radix, p ) );
387
388 if( r < 10 )
389 *(*p)++ = (char)( r + 0x30 );
390 else
391 *(*p)++ = (char)( r + 0x37 );
392
393cleanup:
394
395 return( ret );
396}
397
398/*
399 * Export into an ASCII string
400 */
Paul Bakker23986e52011-04-24 08:57:21 +0000401int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000402{
Paul Bakker23986e52011-04-24 08:57:21 +0000403 int ret = 0;
404 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000405 char *p;
406 mpi T;
407
408 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000409 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000410
411 n = mpi_msb( X );
412 if( radix >= 4 ) n >>= 1;
413 if( radix >= 16 ) n >>= 1;
414 n += 3;
415
416 if( *slen < n )
417 {
418 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000419 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000420 }
421
422 p = s;
Paul Bakker6c591fa2011-05-05 11:49:20 +0000423 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000424
425 if( X->s == -1 )
426 *p++ = '-';
427
428 if( radix == 16 )
429 {
Paul Bakker23986e52011-04-24 08:57:21 +0000430 int c;
431 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000432
Paul Bakker23986e52011-04-24 08:57:21 +0000433 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000434 {
Paul Bakker23986e52011-04-24 08:57:21 +0000435 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000436 {
Paul Bakker23986e52011-04-24 08:57:21 +0000437 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000438
Paul Bakker23986e52011-04-24 08:57:21 +0000439 if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000440 continue;
441
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000442 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000443 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000444 k = 1;
445 }
446 }
447 }
448 else
449 {
450 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000451
452 if( T.s == -1 )
453 T.s = 1;
454
Paul Bakker5121ce52009-01-03 21:22:43 +0000455 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
456 }
457
458 *p++ = '\0';
459 *slen = p - s;
460
461cleanup:
462
Paul Bakker6c591fa2011-05-05 11:49:20 +0000463 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000464
465 return( ret );
466}
467
Paul Bakker335db3f2011-04-25 15:28:35 +0000468#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000469/*
470 * Read X from an opened file
471 */
472int mpi_read_file( mpi *X, int radix, FILE *fin )
473{
Paul Bakkera755ca12011-04-24 09:11:17 +0000474 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000475 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000476 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000477 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000478 * Buffer should have space for (short) label and decimal formatted MPI,
479 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000480 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000481 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000482
483 memset( s, 0, sizeof( s ) );
484 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000485 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000486
487 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000488 if( slen == sizeof( s ) - 2 )
489 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
490
Paul Bakker5121ce52009-01-03 21:22:43 +0000491 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
492 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
493
494 p = s + slen;
495 while( --p >= s )
496 if( mpi_get_digit( &d, radix, *p ) != 0 )
497 break;
498
499 return( mpi_read_string( X, radix, p + 1 ) );
500}
501
502/*
503 * Write X into an opened file (or stdout if fout == NULL)
504 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000505int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000506{
Paul Bakker23986e52011-04-24 08:57:21 +0000507 int ret;
508 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000509 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000510 * Buffer should have space for (short) label and decimal formatted MPI,
511 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000512 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000513 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000514
515 n = sizeof( s );
516 memset( s, 0, n );
517 n -= 2;
518
Paul Bakker23986e52011-04-24 08:57:21 +0000519 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000520
521 if( p == NULL ) p = "";
522
523 plen = strlen( p );
524 slen = strlen( s );
525 s[slen++] = '\r';
526 s[slen++] = '\n';
527
528 if( fout != NULL )
529 {
530 if( fwrite( p, 1, plen, fout ) != plen ||
531 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000532 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000533 }
534 else
535 printf( "%s%s", p, s );
536
537cleanup:
538
539 return( ret );
540}
Paul Bakker335db3f2011-04-25 15:28:35 +0000541#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000542
543/*
544 * Import X from unsigned binary data, big endian
545 */
Paul Bakker23986e52011-04-24 08:57:21 +0000546int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000547{
Paul Bakker23986e52011-04-24 08:57:21 +0000548 int ret;
549 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000550
551 for( n = 0; n < buflen; n++ )
552 if( buf[n] != 0 )
553 break;
554
555 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
556 MPI_CHK( mpi_lset( X, 0 ) );
557
Paul Bakker23986e52011-04-24 08:57:21 +0000558 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000559 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000560
561cleanup:
562
563 return( ret );
564}
565
566/*
567 * Export X into unsigned binary data, big endian
568 */
Paul Bakker23986e52011-04-24 08:57:21 +0000569int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000570{
Paul Bakker23986e52011-04-24 08:57:21 +0000571 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000572
573 n = mpi_size( X );
574
575 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000576 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000577
578 memset( buf, 0, buflen );
579
580 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
581 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
582
583 return( 0 );
584}
585
586/*
587 * Left-shift: X <<= count
588 */
Paul Bakker23986e52011-04-24 08:57:21 +0000589int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000590{
Paul Bakker23986e52011-04-24 08:57:21 +0000591 int ret;
592 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000593 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000594
595 v0 = count / (biL );
596 t1 = count & (biL - 1);
597
598 i = mpi_msb( X ) + count;
599
Paul Bakkerf9688572011-05-05 10:00:45 +0000600 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000601 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
602
603 ret = 0;
604
605 /*
606 * shift by count / limb_size
607 */
608 if( v0 > 0 )
609 {
Paul Bakker23986e52011-04-24 08:57:21 +0000610 for( i = X->n; i > v0; i-- )
611 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000612
Paul Bakker23986e52011-04-24 08:57:21 +0000613 for( ; i > 0; i-- )
614 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000615 }
616
617 /*
618 * shift by count % limb_size
619 */
620 if( t1 > 0 )
621 {
622 for( i = v0; i < X->n; i++ )
623 {
624 r1 = X->p[i] >> (biL - t1);
625 X->p[i] <<= t1;
626 X->p[i] |= r0;
627 r0 = r1;
628 }
629 }
630
631cleanup:
632
633 return( ret );
634}
635
636/*
637 * Right-shift: X >>= count
638 */
Paul Bakker23986e52011-04-24 08:57:21 +0000639int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000640{
Paul Bakker23986e52011-04-24 08:57:21 +0000641 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000642 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000643
644 v0 = count / biL;
645 v1 = count & (biL - 1);
646
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100647 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
648 return mpi_lset( X, 0 );
649
Paul Bakker5121ce52009-01-03 21:22:43 +0000650 /*
651 * shift by count / limb_size
652 */
653 if( v0 > 0 )
654 {
655 for( i = 0; i < X->n - v0; i++ )
656 X->p[i] = X->p[i + v0];
657
658 for( ; i < X->n; i++ )
659 X->p[i] = 0;
660 }
661
662 /*
663 * shift by count % limb_size
664 */
665 if( v1 > 0 )
666 {
Paul Bakker23986e52011-04-24 08:57:21 +0000667 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000668 {
Paul Bakker23986e52011-04-24 08:57:21 +0000669 r1 = X->p[i - 1] << (biL - v1);
670 X->p[i - 1] >>= v1;
671 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000672 r0 = r1;
673 }
674 }
675
676 return( 0 );
677}
678
679/*
680 * Compare unsigned values
681 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000682int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000683{
Paul Bakker23986e52011-04-24 08:57:21 +0000684 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000685
Paul Bakker23986e52011-04-24 08:57:21 +0000686 for( i = X->n; i > 0; i-- )
687 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000688 break;
689
Paul Bakker23986e52011-04-24 08:57:21 +0000690 for( j = Y->n; j > 0; j-- )
691 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000692 break;
693
Paul Bakker23986e52011-04-24 08:57:21 +0000694 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000695 return( 0 );
696
697 if( i > j ) return( 1 );
698 if( j > i ) return( -1 );
699
Paul Bakker23986e52011-04-24 08:57:21 +0000700 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000701 {
Paul Bakker23986e52011-04-24 08:57:21 +0000702 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
703 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000704 }
705
706 return( 0 );
707}
708
709/*
710 * Compare signed values
711 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000712int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000713{
Paul Bakker23986e52011-04-24 08:57:21 +0000714 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000715
Paul Bakker23986e52011-04-24 08:57:21 +0000716 for( i = X->n; i > 0; i-- )
717 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000718 break;
719
Paul Bakker23986e52011-04-24 08:57:21 +0000720 for( j = Y->n; j > 0; j-- )
721 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000722 break;
723
Paul Bakker23986e52011-04-24 08:57:21 +0000724 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000725 return( 0 );
726
727 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000728 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000729
730 if( X->s > 0 && Y->s < 0 ) return( 1 );
731 if( Y->s > 0 && X->s < 0 ) return( -1 );
732
Paul Bakker23986e52011-04-24 08:57:21 +0000733 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000734 {
Paul Bakker23986e52011-04-24 08:57:21 +0000735 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
736 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000737 }
738
739 return( 0 );
740}
741
742/*
743 * Compare signed values
744 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000745int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000746{
747 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000748 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000749
750 *p = ( z < 0 ) ? -z : z;
751 Y.s = ( z < 0 ) ? -1 : 1;
752 Y.n = 1;
753 Y.p = p;
754
755 return( mpi_cmp_mpi( X, &Y ) );
756}
757
758/*
759 * Unsigned addition: X = |A| + |B| (HAC 14.7)
760 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000761int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000762{
Paul Bakker23986e52011-04-24 08:57:21 +0000763 int ret;
764 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000765 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000766
767 if( X == B )
768 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000769 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000770 }
771
772 if( X != A )
773 MPI_CHK( mpi_copy( X, A ) );
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000774
775 /*
776 * X should always be positive as a result of unsigned additions.
777 */
778 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000779
Paul Bakker23986e52011-04-24 08:57:21 +0000780 for( j = B->n; j > 0; j-- )
781 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000782 break;
783
Paul Bakker23986e52011-04-24 08:57:21 +0000784 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000785
786 o = B->p; p = X->p; c = 0;
787
Paul Bakker23986e52011-04-24 08:57:21 +0000788 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000789 {
790 *p += c; c = ( *p < c );
791 *p += *o; c += ( *p < *o );
792 }
793
794 while( c != 0 )
795 {
796 if( i >= X->n )
797 {
798 MPI_CHK( mpi_grow( X, i + 1 ) );
799 p = X->p + i;
800 }
801
Paul Bakker2d319fd2012-09-16 21:34:26 +0000802 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000803 }
804
805cleanup:
806
807 return( ret );
808}
809
810/*
811 * Helper for mpi substraction
812 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000813static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000814{
Paul Bakker23986e52011-04-24 08:57:21 +0000815 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000816 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000817
818 for( i = c = 0; i < n; i++, s++, d++ )
819 {
820 z = ( *d < c ); *d -= c;
821 c = ( *d < *s ) + z; *d -= *s;
822 }
823
824 while( c != 0 )
825 {
826 z = ( *d < c ); *d -= c;
827 c = z; i++; d++;
828 }
829}
830
831/*
832 * Unsigned substraction: X = |A| - |B| (HAC 14.9)
833 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000834int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000835{
836 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000837 int ret;
838 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000839
840 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000841 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000842
Paul Bakker6c591fa2011-05-05 11:49:20 +0000843 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000844
845 if( X == B )
846 {
847 MPI_CHK( mpi_copy( &TB, B ) );
848 B = &TB;
849 }
850
851 if( X != A )
852 MPI_CHK( mpi_copy( X, A ) );
853
Paul Bakker1ef7a532009-06-20 10:50:55 +0000854 /*
855 * X should always be positive as a result of unsigned substractions.
856 */
857 X->s = 1;
858
Paul Bakker5121ce52009-01-03 21:22:43 +0000859 ret = 0;
860
Paul Bakker23986e52011-04-24 08:57:21 +0000861 for( n = B->n; n > 0; n-- )
862 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000863 break;
864
Paul Bakker23986e52011-04-24 08:57:21 +0000865 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000866
867cleanup:
868
Paul Bakker6c591fa2011-05-05 11:49:20 +0000869 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000870
871 return( ret );
872}
873
874/*
875 * Signed addition: X = A + B
876 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000877int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000878{
879 int ret, s = A->s;
880
881 if( A->s * B->s < 0 )
882 {
883 if( mpi_cmp_abs( A, B ) >= 0 )
884 {
885 MPI_CHK( mpi_sub_abs( X, A, B ) );
886 X->s = s;
887 }
888 else
889 {
890 MPI_CHK( mpi_sub_abs( X, B, A ) );
891 X->s = -s;
892 }
893 }
894 else
895 {
896 MPI_CHK( mpi_add_abs( X, A, B ) );
897 X->s = s;
898 }
899
900cleanup:
901
902 return( ret );
903}
904
905/*
906 * Signed substraction: X = A - B
907 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000908int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000909{
910 int ret, s = A->s;
911
912 if( A->s * B->s > 0 )
913 {
914 if( mpi_cmp_abs( A, B ) >= 0 )
915 {
916 MPI_CHK( mpi_sub_abs( X, A, B ) );
917 X->s = s;
918 }
919 else
920 {
921 MPI_CHK( mpi_sub_abs( X, B, A ) );
922 X->s = -s;
923 }
924 }
925 else
926 {
927 MPI_CHK( mpi_add_abs( X, A, B ) );
928 X->s = s;
929 }
930
931cleanup:
932
933 return( ret );
934}
935
936/*
937 * Signed addition: X = A + b
938 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000939int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000940{
941 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000942 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000943
944 p[0] = ( b < 0 ) ? -b : b;
945 _B.s = ( b < 0 ) ? -1 : 1;
946 _B.n = 1;
947 _B.p = p;
948
949 return( mpi_add_mpi( X, A, &_B ) );
950}
951
952/*
953 * Signed substraction: X = A - b
954 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000955int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000956{
957 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000958 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000959
960 p[0] = ( b < 0 ) ? -b : b;
961 _B.s = ( b < 0 ) ? -1 : 1;
962 _B.n = 1;
963 _B.p = p;
964
965 return( mpi_sub_mpi( X, A, &_B ) );
966}
967
968/*
969 * Helper for mpi multiplication
Paul Bakker52b845b2013-06-14 11:36:56 +0200970 */
971static
972#if defined(__APPLE__) && defined(__arm__)
973/*
974 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
975 * appears to need this to prevent bad ARM code generation at -O3.
976 */
977__attribute__ ((noinline))
978#endif
979void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000980{
Paul Bakkera755ca12011-04-24 09:11:17 +0000981 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000982
983#if defined(MULADDC_HUIT)
984 for( ; i >= 8; i -= 8 )
985 {
986 MULADDC_INIT
987 MULADDC_HUIT
988 MULADDC_STOP
989 }
990
991 for( ; i > 0; i-- )
992 {
993 MULADDC_INIT
994 MULADDC_CORE
995 MULADDC_STOP
996 }
997#else
998 for( ; i >= 16; i -= 16 )
999 {
1000 MULADDC_INIT
1001 MULADDC_CORE MULADDC_CORE
1002 MULADDC_CORE MULADDC_CORE
1003 MULADDC_CORE MULADDC_CORE
1004 MULADDC_CORE MULADDC_CORE
1005
1006 MULADDC_CORE MULADDC_CORE
1007 MULADDC_CORE MULADDC_CORE
1008 MULADDC_CORE MULADDC_CORE
1009 MULADDC_CORE MULADDC_CORE
1010 MULADDC_STOP
1011 }
1012
1013 for( ; i >= 8; i -= 8 )
1014 {
1015 MULADDC_INIT
1016 MULADDC_CORE MULADDC_CORE
1017 MULADDC_CORE MULADDC_CORE
1018
1019 MULADDC_CORE MULADDC_CORE
1020 MULADDC_CORE MULADDC_CORE
1021 MULADDC_STOP
1022 }
1023
1024 for( ; i > 0; i-- )
1025 {
1026 MULADDC_INIT
1027 MULADDC_CORE
1028 MULADDC_STOP
1029 }
1030#endif
1031
1032 t++;
1033
1034 do {
1035 *d += c; c = ( *d < c ); d++;
1036 }
1037 while( c != 0 );
1038}
1039
1040/*
1041 * Baseline multiplication: X = A * B (HAC 14.12)
1042 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001043int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001044{
Paul Bakker23986e52011-04-24 08:57:21 +00001045 int ret;
1046 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001047 mpi TA, TB;
1048
Paul Bakker6c591fa2011-05-05 11:49:20 +00001049 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001050
1051 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1052 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1053
Paul Bakker23986e52011-04-24 08:57:21 +00001054 for( i = A->n; i > 0; i-- )
1055 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001056 break;
1057
Paul Bakker23986e52011-04-24 08:57:21 +00001058 for( j = B->n; j > 0; j-- )
1059 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001060 break;
1061
Paul Bakker23986e52011-04-24 08:57:21 +00001062 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001063 MPI_CHK( mpi_lset( X, 0 ) );
1064
Paul Bakker23986e52011-04-24 08:57:21 +00001065 for( i++; j > 0; j-- )
1066 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001067
1068 X->s = A->s * B->s;
1069
1070cleanup:
1071
Paul Bakker6c591fa2011-05-05 11:49:20 +00001072 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001073
1074 return( ret );
1075}
1076
1077/*
1078 * Baseline multiplication: X = A * b
1079 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001080int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001081{
1082 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001083 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001084
1085 _B.s = 1;
1086 _B.n = 1;
1087 _B.p = p;
1088 p[0] = b;
1089
1090 return( mpi_mul_mpi( X, A, &_B ) );
1091}
1092
1093/*
Simon Butcher15f0bbe2015-12-22 15:26:57 +00001094 * Unsigned integer divide - 64bit dividend and 32bit divisor
1095 */
1096static t_uint int_div_int(t_uint u1, t_uint u0, t_uint d, t_uint *r)
1097{
1098#if defined(POLARSSL_HAVE_UDBL)
1099 t_udbl dividend, quotient;
Simon Butcher6901e502016-01-03 22:39:18 +00001100#else
1101 const t_uint radix = (t_uint) 1 << biH;
1102 const t_uint uint_halfword_mask = ( (t_uint) 1 << biH ) - 1;
1103 t_uint d0, d1, q0, q1, rAX, r0, quotient;
1104 t_uint u0_msw, u0_lsw;
1105 size_t s;
Simon Butcher15f0bbe2015-12-22 15:26:57 +00001106#endif
1107
1108 /*
1109 * Check for overflow
1110 */
1111 if(( 0 == d ) || ( u1 >= d ))
1112 {
1113 if (r != NULL) *r = (~0);
1114
1115 return (~0);
1116 }
1117
1118#if defined(POLARSSL_HAVE_UDBL)
1119 dividend = (t_udbl) u1 << biL;
1120 dividend |= (t_udbl) u0;
1121 quotient = dividend / d;
1122 if( quotient > ( (t_udbl) 1 << biL ) - 1 )
1123 quotient = ( (t_udbl) 1 << biL ) - 1;
1124
1125 if( r != NULL )
Simon Butcher6901e502016-01-03 22:39:18 +00001126 *r = (t_uint)( dividend - (quotient * d ) );
Simon Butcher15f0bbe2015-12-22 15:26:57 +00001127
1128 return (t_uint) quotient;
1129#else
1130 const t_uint radix = 1 << biH;
1131 t_uint d0, d1, q0, q1, rAX, r0, quotient;
1132 t_uint u0_msw, u0_lsw;
1133 int s;
1134
1135 /*
1136 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1137 * Vol. 2 - Seminumerical Algorithms, Knuth
1138 */
1139
1140 /*
1141 * Normalize the divisor, d, and dividend, u0, u1
1142 */
1143 s = int_clz( d );
1144 d = d << s;
1145
1146 u1 = u1 << s;
Simon Butcher6901e502016-01-03 22:39:18 +00001147 u1 |= ( u0 >> ( biL - s ) ) & ( -(t_sint)s >> ( biL - 1 ) );
Simon Butcher15f0bbe2015-12-22 15:26:57 +00001148 u0 = u0 << s;
1149
1150 d1 = d >> biH;
Simon Butcher6901e502016-01-03 22:39:18 +00001151 d0 = d & uint_halfword_mask;
Simon Butcher15f0bbe2015-12-22 15:26:57 +00001152
1153 u0_msw = u0 >> biH;
Simon Butcher6901e502016-01-03 22:39:18 +00001154 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15f0bbe2015-12-22 15:26:57 +00001155
1156 /*
1157 * Find the first quotient and remainder
1158 */
1159 q1 = u1 / d1;
1160 r0 = u1 - d1 * q1;
1161
1162 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1163 {
1164 q1 -= 1;
1165 r0 += d1;
1166
1167 if ( r0 >= radix ) break;
1168 }
1169
1170 rAX = (u1 * radix) + (u0_msw - q1 * d);
1171 q0 = rAX / d1;
1172 r0 = rAX - q0 * d1;
1173
1174 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1175 {
1176 q0 -= 1;
1177 r0 += d1;
1178
1179 if ( r0 >= radix ) break;
1180 }
1181
1182 if (r != NULL)
1183 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1184
1185 quotient = q1 * radix + q0;
1186
1187 return quotient;
1188#endif
1189}
1190
1191/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001192 * Division by mpi: A = Q * B + R (HAC 14.20)
1193 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001194int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001195{
Paul Bakker23986e52011-04-24 08:57:21 +00001196 int ret;
1197 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001198 mpi X, Y, Z, T1, T2;
1199
1200 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001201 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001202
Paul Bakker6c591fa2011-05-05 11:49:20 +00001203 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1204 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001205
1206 if( mpi_cmp_abs( A, B ) < 0 )
1207 {
1208 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1209 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1210 return( 0 );
1211 }
1212
1213 MPI_CHK( mpi_copy( &X, A ) );
1214 MPI_CHK( mpi_copy( &Y, B ) );
1215 X.s = Y.s = 1;
1216
1217 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1218 MPI_CHK( mpi_lset( &Z, 0 ) );
1219 MPI_CHK( mpi_grow( &T1, 2 ) );
1220 MPI_CHK( mpi_grow( &T2, 3 ) );
1221
1222 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001223 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001224 {
1225 k = biL - 1 - k;
1226 MPI_CHK( mpi_shift_l( &X, k ) );
1227 MPI_CHK( mpi_shift_l( &Y, k ) );
1228 }
1229 else k = 0;
1230
1231 n = X.n - 1;
1232 t = Y.n - 1;
Paul Bakkerc110d022012-10-19 12:15:08 +00001233 MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001234
1235 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1236 {
1237 Z.p[n - t]++;
Paul Bakker78e81962013-12-31 11:16:03 +01001238 MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001239 }
Paul Bakker78e81962013-12-31 11:16:03 +01001240 MPI_CHK( mpi_shift_r( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001241
1242 for( i = n; i > t ; i-- )
1243 {
1244 if( X.p[i] >= Y.p[t] )
1245 Z.p[i - t - 1] = ~0;
1246 else
1247 {
Simon Butcher15f0bbe2015-12-22 15:26:57 +00001248 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 +00001249 }
1250
1251 Z.p[i - t - 1]++;
1252 do
1253 {
1254 Z.p[i - t - 1]--;
1255
1256 MPI_CHK( mpi_lset( &T1, 0 ) );
1257 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1258 T1.p[1] = Y.p[t];
1259 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1260
1261 MPI_CHK( mpi_lset( &T2, 0 ) );
1262 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1263 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1264 T2.p[2] = X.p[i];
1265 }
1266 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1267
1268 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1269 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1270 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1271
1272 if( mpi_cmp_int( &X, 0 ) < 0 )
1273 {
1274 MPI_CHK( mpi_copy( &T1, &Y ) );
1275 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1276 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1277 Z.p[i - t - 1]--;
1278 }
1279 }
1280
1281 if( Q != NULL )
1282 {
Paul Bakker78e81962013-12-31 11:16:03 +01001283 MPI_CHK( mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001284 Q->s = A->s * B->s;
1285 }
1286
1287 if( R != NULL )
1288 {
Paul Bakker78e81962013-12-31 11:16:03 +01001289 MPI_CHK( mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001290 X.s = A->s;
Paul Bakker78e81962013-12-31 11:16:03 +01001291 MPI_CHK( mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001292
Paul Bakker5121ce52009-01-03 21:22:43 +00001293 if( mpi_cmp_int( R, 0 ) == 0 )
1294 R->s = 1;
1295 }
1296
1297cleanup:
1298
Paul Bakker6c591fa2011-05-05 11:49:20 +00001299 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1300 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001301
1302 return( ret );
1303}
1304
1305/*
1306 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001307 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001308int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001309{
1310 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001311 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001312
1313 p[0] = ( b < 0 ) ? -b : b;
1314 _B.s = ( b < 0 ) ? -1 : 1;
1315 _B.n = 1;
1316 _B.p = p;
1317
1318 return( mpi_div_mpi( Q, R, A, &_B ) );
1319}
1320
1321/*
1322 * Modulo: R = A mod B
1323 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001324int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001325{
1326 int ret;
1327
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001328 if( mpi_cmp_int( B, 0 ) < 0 )
1329 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1330
Paul Bakker5121ce52009-01-03 21:22:43 +00001331 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1332
1333 while( mpi_cmp_int( R, 0 ) < 0 )
1334 MPI_CHK( mpi_add_mpi( R, R, B ) );
1335
1336 while( mpi_cmp_mpi( R, B ) >= 0 )
1337 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1338
1339cleanup:
1340
1341 return( ret );
1342}
1343
1344/*
1345 * Modulo: r = A mod b
1346 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001347int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001348{
Paul Bakker23986e52011-04-24 08:57:21 +00001349 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001350 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001351
1352 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001353 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001354
1355 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001356 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001357
1358 /*
1359 * handle trivial cases
1360 */
1361 if( b == 1 )
1362 {
1363 *r = 0;
1364 return( 0 );
1365 }
1366
1367 if( b == 2 )
1368 {
1369 *r = A->p[0] & 1;
1370 return( 0 );
1371 }
1372
1373 /*
1374 * general case
1375 */
Paul Bakker23986e52011-04-24 08:57:21 +00001376 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001377 {
Paul Bakker23986e52011-04-24 08:57:21 +00001378 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001379 y = ( y << biH ) | ( x >> biH );
1380 z = y / b;
1381 y -= z * b;
1382
1383 x <<= biH;
1384 y = ( y << biH ) | ( x >> biH );
1385 z = y / b;
1386 y -= z * b;
1387 }
1388
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001389 /*
1390 * If A is negative, then the current y represents a negative value.
1391 * Flipping it to the positive side.
1392 */
1393 if( A->s < 0 && y != 0 )
1394 y = b - y;
1395
Paul Bakker5121ce52009-01-03 21:22:43 +00001396 *r = y;
1397
1398 return( 0 );
1399}
1400
1401/*
1402 * Fast Montgomery initialization (thanks to Tom St Denis)
1403 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001404static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001405{
Paul Bakkera755ca12011-04-24 09:11:17 +00001406 t_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnard397858b2014-03-11 13:47:05 +01001407 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001408
1409 x = m0;
1410 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001411
Manuel Pégourié-Gonnard397858b2014-03-11 13:47:05 +01001412 for( i = biL; i >= 8; i /= 2 )
1413 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001414
1415 *mm = ~x + 1;
1416}
1417
1418/*
1419 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1420 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001421static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001422{
Paul Bakker23986e52011-04-24 08:57:21 +00001423 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001424 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001425
1426 memset( T->p, 0, T->n * ciL );
1427
1428 d = T->p;
1429 n = N->n;
1430 m = ( B->n < n ) ? B->n : n;
1431
1432 for( i = 0; i < n; i++ )
1433 {
1434 /*
1435 * T = (T + u0*B + u1*N) / 2^biL
1436 */
1437 u0 = A->p[i];
1438 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1439
1440 mpi_mul_hlp( m, B->p, d, u0 );
1441 mpi_mul_hlp( n, N->p, d, u1 );
1442
1443 *d++ = u0; d[n + 1] = 0;
1444 }
1445
1446 memcpy( A->p, d, (n + 1) * ciL );
1447
1448 if( mpi_cmp_abs( A, N ) >= 0 )
1449 mpi_sub_hlp( n, N->p, A->p );
1450 else
1451 /* prevent timing attacks */
1452 mpi_sub_hlp( n, A->p, T->p );
1453}
1454
1455/*
1456 * Montgomery reduction: A = A * R^-1 mod N
1457 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001458static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001459{
Paul Bakkera755ca12011-04-24 09:11:17 +00001460 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001461 mpi U;
1462
Paul Bakker8ddb6452013-02-27 14:56:33 +01001463 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001464 U.p = &z;
1465
1466 mpi_montmul( A, &U, N, mm, T );
1467}
1468
1469/*
1470 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1471 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001472int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001473{
Paul Bakker23986e52011-04-24 08:57:21 +00001474 int ret;
1475 size_t wbits, wsize, one = 1;
1476 size_t i, j, nblimbs;
1477 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001478 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001479 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1480 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001481
1482 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001483 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001484
Paul Bakkerf6198c12012-05-16 08:02:29 +00001485 if( mpi_cmp_int( E, 0 ) < 0 )
1486 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1487
1488 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001489 * Init temps and window size
1490 */
1491 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001492 mpi_init( &RR ); mpi_init( &T );
Manuel Pégourié-Gonnard7fd620b2014-01-18 19:05:23 +01001493 mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001494 memset( W, 0, sizeof( W ) );
1495
1496 i = mpi_msb( E );
1497
1498 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1499 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1500
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001501 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1502 wsize = POLARSSL_MPI_WINDOW_SIZE;
1503
Paul Bakker5121ce52009-01-03 21:22:43 +00001504 j = N->n + 1;
1505 MPI_CHK( mpi_grow( X, j ) );
1506 MPI_CHK( mpi_grow( &W[1], j ) );
1507 MPI_CHK( mpi_grow( &T, j * 2 ) );
1508
1509 /*
Paul Bakker50546922012-05-19 08:40:49 +00001510 * Compensate for negative A (and correct at the end)
1511 */
1512 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001513 if( neg )
1514 {
1515 MPI_CHK( mpi_copy( &Apos, A ) );
1516 Apos.s = 1;
1517 A = &Apos;
1518 }
1519
1520 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001521 * If 1st call, pre-compute R^2 mod N
1522 */
1523 if( _RR == NULL || _RR->p == NULL )
1524 {
1525 MPI_CHK( mpi_lset( &RR, 1 ) );
1526 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1527 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1528
1529 if( _RR != NULL )
1530 memcpy( _RR, &RR, sizeof( mpi ) );
1531 }
1532 else
1533 memcpy( &RR, _RR, sizeof( mpi ) );
1534
1535 /*
1536 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1537 */
1538 if( mpi_cmp_mpi( A, N ) >= 0 )
Paul Bakker1dc45f12014-01-23 20:38:35 +01001539 {
1540 MPI_CHK( mpi_mod_mpi( &W[1], A, N ) );
1541 }
1542 else
1543 MPI_CHK( mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001544
1545 mpi_montmul( &W[1], &RR, N, mm, &T );
1546
1547 /*
1548 * X = R^2 * R^-1 mod N = R mod N
1549 */
1550 MPI_CHK( mpi_copy( X, &RR ) );
1551 mpi_montred( X, N, mm, &T );
1552
1553 if( wsize > 1 )
1554 {
1555 /*
1556 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1557 */
Paul Bakker23986e52011-04-24 08:57:21 +00001558 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001559
1560 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1561 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1562
1563 for( i = 0; i < wsize - 1; i++ )
1564 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakkerc3ec63d2013-10-29 16:18:35 +01001565
Paul Bakker5121ce52009-01-03 21:22:43 +00001566 /*
1567 * W[i] = W[i - 1] * W[1]
1568 */
Paul Bakker23986e52011-04-24 08:57:21 +00001569 for( i = j + 1; i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001570 {
1571 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1572 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1573
1574 mpi_montmul( &W[i], &W[1], N, mm, &T );
1575 }
1576 }
1577
1578 nblimbs = E->n;
1579 bufsize = 0;
1580 nbits = 0;
1581 wbits = 0;
1582 state = 0;
1583
1584 while( 1 )
1585 {
1586 if( bufsize == 0 )
1587 {
Paul Bakkerc3ec63d2013-10-29 16:18:35 +01001588 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001589 break;
1590
Paul Bakkerc3ec63d2013-10-29 16:18:35 +01001591 nblimbs--;
1592
Paul Bakkera755ca12011-04-24 09:11:17 +00001593 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001594 }
1595
1596 bufsize--;
1597
1598 ei = (E->p[nblimbs] >> bufsize) & 1;
1599
1600 /*
1601 * skip leading 0s
1602 */
1603 if( ei == 0 && state == 0 )
1604 continue;
1605
1606 if( ei == 0 && state == 1 )
1607 {
1608 /*
1609 * out of window, square X
1610 */
1611 mpi_montmul( X, X, N, mm, &T );
1612 continue;
1613 }
1614
1615 /*
1616 * add ei to current window
1617 */
1618 state = 2;
1619
1620 nbits++;
1621 wbits |= (ei << (wsize - nbits));
1622
1623 if( nbits == wsize )
1624 {
1625 /*
1626 * X = X^wsize R^-1 mod N
1627 */
1628 for( i = 0; i < wsize; i++ )
1629 mpi_montmul( X, X, N, mm, &T );
1630
1631 /*
1632 * X = X * W[wbits] R^-1 mod N
1633 */
1634 mpi_montmul( X, &W[wbits], N, mm, &T );
1635
1636 state--;
1637 nbits = 0;
1638 wbits = 0;
1639 }
1640 }
1641
1642 /*
1643 * process the remaining bits
1644 */
1645 for( i = 0; i < nbits; i++ )
1646 {
1647 mpi_montmul( X, X, N, mm, &T );
1648
1649 wbits <<= 1;
1650
Paul Bakker23986e52011-04-24 08:57:21 +00001651 if( (wbits & (one << wsize)) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001652 mpi_montmul( X, &W[1], N, mm, &T );
1653 }
1654
1655 /*
1656 * X = A^E * R * R^-1 mod N = A^E mod N
1657 */
1658 mpi_montred( X, N, mm, &T );
1659
Paul Bakkerf6198c12012-05-16 08:02:29 +00001660 if( neg )
1661 {
1662 X->s = -1;
Paul Bakker1dc45f12014-01-23 20:38:35 +01001663 MPI_CHK( mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001664 }
1665
Paul Bakker5121ce52009-01-03 21:22:43 +00001666cleanup:
1667
Paul Bakker23986e52011-04-24 08:57:21 +00001668 for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001669 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001670
Paul Bakkerf6198c12012-05-16 08:02:29 +00001671 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001672
Paul Bakker6995efe2014-03-31 12:08:17 +02001673 if( _RR == NULL || _RR->p == NULL )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001674 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001675
1676 return( ret );
1677}
1678
Paul Bakker5121ce52009-01-03 21:22:43 +00001679/*
1680 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1681 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001682int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001683{
Paul Bakker23986e52011-04-24 08:57:21 +00001684 int ret;
1685 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001686 mpi TG, TA, TB;
1687
Paul Bakker6c591fa2011-05-05 11:49:20 +00001688 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001689
Paul Bakker5121ce52009-01-03 21:22:43 +00001690 MPI_CHK( mpi_copy( &TA, A ) );
1691 MPI_CHK( mpi_copy( &TB, B ) );
1692
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001693 lz = mpi_lsb( &TA );
1694 lzt = mpi_lsb( &TB );
1695
1696 if ( lzt < lz )
1697 lz = lzt;
1698
1699 MPI_CHK( mpi_shift_r( &TA, lz ) );
1700 MPI_CHK( mpi_shift_r( &TB, lz ) );
1701
Paul Bakker5121ce52009-01-03 21:22:43 +00001702 TA.s = TB.s = 1;
1703
1704 while( mpi_cmp_int( &TA, 0 ) != 0 )
1705 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001706 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1707 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001708
1709 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1710 {
1711 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1712 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1713 }
1714 else
1715 {
1716 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1717 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1718 }
1719 }
1720
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001721 MPI_CHK( mpi_shift_l( &TB, lz ) );
1722 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001723
1724cleanup:
1725
Paul Bakker6c591fa2011-05-05 11:49:20 +00001726 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001727
1728 return( ret );
1729}
1730
Paul Bakker358d3252014-04-30 16:11:39 +02001731/*
1732 * Fill X with size bytes of random.
1733 *
1734 * Use a temporary bytes representation to make sure the result is the same
1735 * regardless of the platform endianness (usefull when f_rng is actually
1736 * deterministic, eg for tests).
1737 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001738int mpi_fill_random( mpi *X, size_t size,
1739 int (*f_rng)(void *, unsigned char *, size_t),
1740 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001741{
Paul Bakker23986e52011-04-24 08:57:21 +00001742 int ret;
Paul Bakker358d3252014-04-30 16:11:39 +02001743 unsigned char buf[POLARSSL_MPI_MAX_SIZE];
1744
1745 if( size > POLARSSL_MPI_MAX_SIZE )
1746 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001747
Paul Bakker39dfdac2012-02-12 17:17:27 +00001748 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001749 MPI_CHK( mpi_lset( X, 0 ) );
1750
Paul Bakker358d3252014-04-30 16:11:39 +02001751 MPI_CHK( f_rng( p_rng, buf, size ) );
1752 MPI_CHK( mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001753
1754cleanup:
1755 return( ret );
1756}
1757
Paul Bakker5121ce52009-01-03 21:22:43 +00001758/*
1759 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1760 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001761int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001762{
1763 int ret;
1764 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1765
1766 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001767 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001768
Paul Bakker6c591fa2011-05-05 11:49:20 +00001769 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1770 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1771 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001772
1773 MPI_CHK( mpi_gcd( &G, A, N ) );
1774
1775 if( mpi_cmp_int( &G, 1 ) != 0 )
1776 {
Paul Bakker40e46942009-01-03 21:51:57 +00001777 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001778 goto cleanup;
1779 }
1780
1781 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1782 MPI_CHK( mpi_copy( &TU, &TA ) );
1783 MPI_CHK( mpi_copy( &TB, N ) );
1784 MPI_CHK( mpi_copy( &TV, N ) );
1785
1786 MPI_CHK( mpi_lset( &U1, 1 ) );
1787 MPI_CHK( mpi_lset( &U2, 0 ) );
1788 MPI_CHK( mpi_lset( &V1, 0 ) );
1789 MPI_CHK( mpi_lset( &V2, 1 ) );
1790
1791 do
1792 {
1793 while( ( TU.p[0] & 1 ) == 0 )
1794 {
1795 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1796
1797 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1798 {
1799 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1800 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1801 }
1802
1803 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1804 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1805 }
1806
1807 while( ( TV.p[0] & 1 ) == 0 )
1808 {
1809 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1810
1811 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1812 {
1813 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1814 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1815 }
1816
1817 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1818 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1819 }
1820
1821 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1822 {
1823 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1824 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1825 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1826 }
1827 else
1828 {
1829 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1830 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1831 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1832 }
1833 }
1834 while( mpi_cmp_int( &TU, 0 ) != 0 );
1835
1836 while( mpi_cmp_int( &V1, 0 ) < 0 )
1837 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1838
1839 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1840 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1841
1842 MPI_CHK( mpi_copy( X, &V1 ) );
1843
1844cleanup:
1845
Paul Bakker6c591fa2011-05-05 11:49:20 +00001846 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1847 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1848 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001849
1850 return( ret );
1851}
1852
Paul Bakkerd9374b02012-11-02 11:02:58 +00001853#if defined(POLARSSL_GENPRIME)
1854
Paul Bakker5121ce52009-01-03 21:22:43 +00001855static const int small_prime[] =
1856{
1857 3, 5, 7, 11, 13, 17, 19, 23,
1858 29, 31, 37, 41, 43, 47, 53, 59,
1859 61, 67, 71, 73, 79, 83, 89, 97,
1860 101, 103, 107, 109, 113, 127, 131, 137,
1861 139, 149, 151, 157, 163, 167, 173, 179,
1862 181, 191, 193, 197, 199, 211, 223, 227,
1863 229, 233, 239, 241, 251, 257, 263, 269,
1864 271, 277, 281, 283, 293, 307, 311, 313,
1865 317, 331, 337, 347, 349, 353, 359, 367,
1866 373, 379, 383, 389, 397, 401, 409, 419,
1867 421, 431, 433, 439, 443, 449, 457, 461,
1868 463, 467, 479, 487, 491, 499, 503, 509,
1869 521, 523, 541, 547, 557, 563, 569, 571,
1870 577, 587, 593, 599, 601, 607, 613, 617,
1871 619, 631, 641, 643, 647, 653, 659, 661,
1872 673, 677, 683, 691, 701, 709, 719, 727,
1873 733, 739, 743, 751, 757, 761, 769, 773,
1874 787, 797, 809, 811, 821, 823, 827, 829,
1875 839, 853, 857, 859, 863, 877, 881, 883,
1876 887, 907, 911, 919, 929, 937, 941, 947,
1877 953, 967, 971, 977, 983, 991, 997, -103
1878};
1879
1880/*
1881 * Miller-Rabin primality test (HAC 4.24)
1882 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001883int mpi_is_prime( mpi *X,
1884 int (*f_rng)(void *, unsigned char *, size_t),
1885 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001886{
Paul Bakker23986e52011-04-24 08:57:21 +00001887 int ret, xs;
1888 size_t i, j, n, s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001889 mpi W, R, T, A, RR;
Paul Bakker5121ce52009-01-03 21:22:43 +00001890
Paul Bakker48eab262009-06-25 21:25:49 +00001891 if( mpi_cmp_int( X, 0 ) == 0 ||
1892 mpi_cmp_int( X, 1 ) == 0 )
1893 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1894
1895 if( mpi_cmp_int( X, 2 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001896 return( 0 );
1897
Paul Bakker6c591fa2011-05-05 11:49:20 +00001898 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
1899 mpi_init( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001900
1901 xs = X->s; X->s = 1;
1902
1903 /*
1904 * test trivial factors first
1905 */
1906 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001907 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001908
1909 for( i = 0; small_prime[i] > 0; i++ )
1910 {
Paul Bakkera755ca12011-04-24 09:11:17 +00001911 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001912
1913 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
1914 return( 0 );
1915
1916 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1917
1918 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001919 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001920 }
1921
1922 /*
1923 * W = |X| - 1
1924 * R = W >> lsb( W )
1925 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001926 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001927 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001928 MPI_CHK( mpi_copy( &R, &W ) );
1929 MPI_CHK( mpi_shift_r( &R, s ) );
1930
1931 i = mpi_msb( X );
1932 /*
1933 * HAC, table 4.4
1934 */
1935 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1936 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1937 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1938
1939 for( i = 0; i < n; i++ )
1940 {
1941 /*
1942 * pick a random A, 1 < A < |X| - 1
1943 */
Paul Bakker901c6562012-04-20 13:25:38 +00001944 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
Paul Bakkerb94081b2011-01-05 15:53:06 +00001946 if( mpi_cmp_mpi( &A, &W ) >= 0 )
1947 {
1948 j = mpi_msb( &A ) - mpi_msb( &W );
1949 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1950 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001951 A.p[0] |= 3;
1952
1953 /*
1954 * A = A^R mod |X|
1955 */
1956 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1957
1958 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1959 mpi_cmp_int( &A, 1 ) == 0 )
1960 continue;
1961
1962 j = 1;
1963 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1964 {
1965 /*
1966 * A = A * A mod |X|
1967 */
1968 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1969 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1970
1971 if( mpi_cmp_int( &A, 1 ) == 0 )
1972 break;
1973
1974 j++;
1975 }
1976
1977 /*
1978 * not prime if A != |X| - 1 or A == 1
1979 */
1980 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1981 mpi_cmp_int( &A, 1 ) == 0 )
1982 {
Paul Bakker40e46942009-01-03 21:51:57 +00001983 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001984 break;
1985 }
1986 }
1987
1988cleanup:
1989
1990 X->s = xs;
1991
Paul Bakker6c591fa2011-05-05 11:49:20 +00001992 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
1993 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001994
1995 return( ret );
1996}
1997
1998/*
1999 * Prime number generation
2000 */
Paul Bakker23986e52011-04-24 08:57:21 +00002001int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002002 int (*f_rng)(void *, unsigned char *, size_t),
2003 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002004{
Paul Bakker23986e52011-04-24 08:57:21 +00002005 int ret;
2006 size_t k, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00002007 mpi Y;
2008
Paul Bakkerfe3256e2011-11-25 12:11:43 +00002009 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00002010 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002011
Paul Bakker6c591fa2011-05-05 11:49:20 +00002012 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002013
2014 n = BITS_TO_LIMBS( nbits );
2015
Paul Bakker901c6562012-04-20 13:25:38 +00002016 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002017
2018 k = mpi_msb( X );
2019 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
2020 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
2021
2022 X->p[0] |= 3;
2023
2024 if( dh_flag == 0 )
2025 {
2026 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
2027 {
Paul Bakker40e46942009-01-03 21:51:57 +00002028 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002029 goto cleanup;
2030
2031 MPI_CHK( mpi_add_int( X, X, 2 ) );
2032 }
2033 }
2034 else
2035 {
2036 MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
2037 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2038
2039 while( 1 )
2040 {
2041 if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
2042 {
2043 if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
2044 break;
2045
Paul Bakker40e46942009-01-03 21:51:57 +00002046 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002047 goto cleanup;
2048 }
2049
Paul Bakker40e46942009-01-03 21:51:57 +00002050 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002051 goto cleanup;
2052
2053 MPI_CHK( mpi_add_int( &Y, X, 1 ) );
2054 MPI_CHK( mpi_add_int( X, X, 2 ) );
2055 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2056 }
2057 }
2058
2059cleanup:
2060
Paul Bakker6c591fa2011-05-05 11:49:20 +00002061 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002062
2063 return( ret );
2064}
2065
2066#endif
2067
Paul Bakker40e46942009-01-03 21:51:57 +00002068#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002069
Paul Bakker23986e52011-04-24 08:57:21 +00002070#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002071
2072static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2073{
2074 { 693, 609, 21 },
2075 { 1764, 868, 28 },
2076 { 768454923, 542167814, 1 }
2077};
2078
Paul Bakker5121ce52009-01-03 21:22:43 +00002079/*
2080 * Checkup routine
2081 */
2082int mpi_self_test( int verbose )
2083{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002084 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002085 mpi A, E, N, X, Y, U, V;
2086
Paul Bakker6c591fa2011-05-05 11:49:20 +00002087 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2088 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002089
2090 MPI_CHK( mpi_read_string( &A, 16,
2091 "EFE021C2645FD1DC586E69184AF4A31E" \
2092 "D5F53E93B5F123FA41680867BA110131" \
2093 "944FE7952E2517337780CB0DB80E61AA" \
2094 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2095
2096 MPI_CHK( mpi_read_string( &E, 16,
2097 "B2E7EFD37075B9F03FF989C7C5051C20" \
2098 "34D2A323810251127E7BF8625A4F49A5" \
2099 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2100 "5B5C25763222FEFCCFC38B832366C29E" ) );
2101
2102 MPI_CHK( mpi_read_string( &N, 16,
2103 "0066A198186C18C10B2F5ED9B522752A" \
2104 "9830B69916E535C8F047518A889A43A5" \
2105 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2106
2107 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2108
2109 MPI_CHK( mpi_read_string( &U, 16,
2110 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2111 "9E857EA95A03512E2BAE7391688D264A" \
2112 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2113 "8001B72E848A38CAE1C65F78E56ABDEF" \
2114 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2115 "ECF677152EF804370C1A305CAF3B5BF1" \
2116 "30879B56C61DE584A0F53A2447A51E" ) );
2117
2118 if( verbose != 0 )
2119 printf( " MPI test #1 (mul_mpi): " );
2120
2121 if( mpi_cmp_mpi( &X, &U ) != 0 )
2122 {
2123 if( verbose != 0 )
2124 printf( "failed\n" );
2125
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002126 ret = 1;
2127 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002128 }
2129
2130 if( verbose != 0 )
2131 printf( "passed\n" );
2132
2133 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2134
2135 MPI_CHK( mpi_read_string( &U, 16,
2136 "256567336059E52CAE22925474705F39A94" ) );
2137
2138 MPI_CHK( mpi_read_string( &V, 16,
2139 "6613F26162223DF488E9CD48CC132C7A" \
2140 "0AC93C701B001B092E4E5B9F73BCD27B" \
2141 "9EE50D0657C77F374E903CDFA4C642" ) );
2142
2143 if( verbose != 0 )
2144 printf( " MPI test #2 (div_mpi): " );
2145
2146 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2147 mpi_cmp_mpi( &Y, &V ) != 0 )
2148 {
2149 if( verbose != 0 )
2150 printf( "failed\n" );
2151
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002152 ret = 1;
2153 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002154 }
2155
2156 if( verbose != 0 )
2157 printf( "passed\n" );
2158
2159 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2160
2161 MPI_CHK( mpi_read_string( &U, 16,
2162 "36E139AEA55215609D2816998ED020BB" \
2163 "BD96C37890F65171D948E9BC7CBAA4D9" \
2164 "325D24D6A3C12710F10A09FA08AB87" ) );
2165
2166 if( verbose != 0 )
2167 printf( " MPI test #3 (exp_mod): " );
2168
2169 if( mpi_cmp_mpi( &X, &U ) != 0 )
2170 {
2171 if( verbose != 0 )
2172 printf( "failed\n" );
2173
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002174 ret = 1;
2175 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002176 }
2177
2178 if( verbose != 0 )
2179 printf( "passed\n" );
2180
Paul Bakker5690efc2011-05-26 13:16:06 +00002181#if defined(POLARSSL_GENPRIME)
Paul Bakker5121ce52009-01-03 21:22:43 +00002182 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2183
2184 MPI_CHK( mpi_read_string( &U, 16,
2185 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2186 "C3DBA76456363A10869622EAC2DD84EC" \
2187 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2188
2189 if( verbose != 0 )
2190 printf( " MPI test #4 (inv_mod): " );
2191
2192 if( mpi_cmp_mpi( &X, &U ) != 0 )
2193 {
2194 if( verbose != 0 )
2195 printf( "failed\n" );
2196
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002197 ret = 1;
2198 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002199 }
2200
2201 if( verbose != 0 )
2202 printf( "passed\n" );
Paul Bakker5690efc2011-05-26 13:16:06 +00002203#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002204
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002205 if( verbose != 0 )
2206 printf( " MPI test #5 (simple gcd): " );
2207
2208 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2209 {
2210 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002211 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002212
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002213 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002214
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002215 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2216 {
2217 if( verbose != 0 )
2218 printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002219
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002220 ret = 1;
2221 goto cleanup;
2222 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002223 }
2224
2225 if( verbose != 0 )
2226 printf( "passed\n" );
2227
Paul Bakker5121ce52009-01-03 21:22:43 +00002228cleanup:
2229
2230 if( ret != 0 && verbose != 0 )
2231 printf( "Unexpected error, return code = %08X\n", ret );
2232
Paul Bakker6c591fa2011-05-05 11:49:20 +00002233 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2234 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002235
2236 if( verbose != 0 )
2237 printf( "\n" );
2238
2239 return( ret );
2240}
2241
2242#endif
2243
2244#endif