blob: 85514a300598e26051bb7fea92be1111d8506a8a [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
Simon Butcher15f0bbe2015-12-22 15:26:57 +00001130
1131 /*
1132 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1133 * Vol. 2 - Seminumerical Algorithms, Knuth
1134 */
1135
1136 /*
1137 * Normalize the divisor, d, and dividend, u0, u1
1138 */
1139 s = int_clz( d );
1140 d = d << s;
1141
1142 u1 = u1 << s;
Simon Butcher6901e502016-01-03 22:39:18 +00001143 u1 |= ( u0 >> ( biL - s ) ) & ( -(t_sint)s >> ( biL - 1 ) );
Simon Butcher15f0bbe2015-12-22 15:26:57 +00001144 u0 = u0 << s;
1145
1146 d1 = d >> biH;
Simon Butcher6901e502016-01-03 22:39:18 +00001147 d0 = d & uint_halfword_mask;
Simon Butcher15f0bbe2015-12-22 15:26:57 +00001148
1149 u0_msw = u0 >> biH;
Simon Butcher6901e502016-01-03 22:39:18 +00001150 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15f0bbe2015-12-22 15:26:57 +00001151
1152 /*
1153 * Find the first quotient and remainder
1154 */
1155 q1 = u1 / d1;
1156 r0 = u1 - d1 * q1;
1157
1158 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1159 {
1160 q1 -= 1;
1161 r0 += d1;
1162
1163 if ( r0 >= radix ) break;
1164 }
1165
1166 rAX = (u1 * radix) + (u0_msw - q1 * d);
1167 q0 = rAX / d1;
1168 r0 = rAX - q0 * d1;
1169
1170 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1171 {
1172 q0 -= 1;
1173 r0 += d1;
1174
1175 if ( r0 >= radix ) break;
1176 }
1177
1178 if (r != NULL)
1179 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1180
1181 quotient = q1 * radix + q0;
1182
1183 return quotient;
1184#endif
1185}
1186
1187/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001188 * Division by mpi: A = Q * B + R (HAC 14.20)
1189 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001190int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001191{
Paul Bakker23986e52011-04-24 08:57:21 +00001192 int ret;
1193 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001194 mpi X, Y, Z, T1, T2;
1195
1196 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001197 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001198
Paul Bakker6c591fa2011-05-05 11:49:20 +00001199 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1200 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001201
1202 if( mpi_cmp_abs( A, B ) < 0 )
1203 {
1204 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1205 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1206 return( 0 );
1207 }
1208
1209 MPI_CHK( mpi_copy( &X, A ) );
1210 MPI_CHK( mpi_copy( &Y, B ) );
1211 X.s = Y.s = 1;
1212
1213 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1214 MPI_CHK( mpi_lset( &Z, 0 ) );
1215 MPI_CHK( mpi_grow( &T1, 2 ) );
1216 MPI_CHK( mpi_grow( &T2, 3 ) );
1217
1218 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001219 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001220 {
1221 k = biL - 1 - k;
1222 MPI_CHK( mpi_shift_l( &X, k ) );
1223 MPI_CHK( mpi_shift_l( &Y, k ) );
1224 }
1225 else k = 0;
1226
1227 n = X.n - 1;
1228 t = Y.n - 1;
Paul Bakkerc110d022012-10-19 12:15:08 +00001229 MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001230
1231 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1232 {
1233 Z.p[n - t]++;
Paul Bakker78e81962013-12-31 11:16:03 +01001234 MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001235 }
Paul Bakker78e81962013-12-31 11:16:03 +01001236 MPI_CHK( mpi_shift_r( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001237
1238 for( i = n; i > t ; i-- )
1239 {
1240 if( X.p[i] >= Y.p[t] )
1241 Z.p[i - t - 1] = ~0;
1242 else
1243 {
Simon Butcher15f0bbe2015-12-22 15:26:57 +00001244 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 +00001245 }
1246
1247 Z.p[i - t - 1]++;
1248 do
1249 {
1250 Z.p[i - t - 1]--;
1251
1252 MPI_CHK( mpi_lset( &T1, 0 ) );
1253 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1254 T1.p[1] = Y.p[t];
1255 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1256
1257 MPI_CHK( mpi_lset( &T2, 0 ) );
1258 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1259 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1260 T2.p[2] = X.p[i];
1261 }
1262 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1263
1264 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1265 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1266 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1267
1268 if( mpi_cmp_int( &X, 0 ) < 0 )
1269 {
1270 MPI_CHK( mpi_copy( &T1, &Y ) );
1271 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1272 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1273 Z.p[i - t - 1]--;
1274 }
1275 }
1276
1277 if( Q != NULL )
1278 {
Paul Bakker78e81962013-12-31 11:16:03 +01001279 MPI_CHK( mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001280 Q->s = A->s * B->s;
1281 }
1282
1283 if( R != NULL )
1284 {
Paul Bakker78e81962013-12-31 11:16:03 +01001285 MPI_CHK( mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001286 X.s = A->s;
Paul Bakker78e81962013-12-31 11:16:03 +01001287 MPI_CHK( mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001288
Paul Bakker5121ce52009-01-03 21:22:43 +00001289 if( mpi_cmp_int( R, 0 ) == 0 )
1290 R->s = 1;
1291 }
1292
1293cleanup:
1294
Paul Bakker6c591fa2011-05-05 11:49:20 +00001295 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1296 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001297
1298 return( ret );
1299}
1300
1301/*
1302 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001303 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001304int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001305{
1306 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001307 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001308
1309 p[0] = ( b < 0 ) ? -b : b;
1310 _B.s = ( b < 0 ) ? -1 : 1;
1311 _B.n = 1;
1312 _B.p = p;
1313
1314 return( mpi_div_mpi( Q, R, A, &_B ) );
1315}
1316
1317/*
1318 * Modulo: R = A mod B
1319 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001320int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001321{
1322 int ret;
1323
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001324 if( mpi_cmp_int( B, 0 ) < 0 )
1325 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1326
Paul Bakker5121ce52009-01-03 21:22:43 +00001327 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1328
1329 while( mpi_cmp_int( R, 0 ) < 0 )
1330 MPI_CHK( mpi_add_mpi( R, R, B ) );
1331
1332 while( mpi_cmp_mpi( R, B ) >= 0 )
1333 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1334
1335cleanup:
1336
1337 return( ret );
1338}
1339
1340/*
1341 * Modulo: r = A mod b
1342 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001343int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001344{
Paul Bakker23986e52011-04-24 08:57:21 +00001345 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001346 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001347
1348 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001349 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001350
1351 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001352 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001353
1354 /*
1355 * handle trivial cases
1356 */
1357 if( b == 1 )
1358 {
1359 *r = 0;
1360 return( 0 );
1361 }
1362
1363 if( b == 2 )
1364 {
1365 *r = A->p[0] & 1;
1366 return( 0 );
1367 }
1368
1369 /*
1370 * general case
1371 */
Paul Bakker23986e52011-04-24 08:57:21 +00001372 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001373 {
Paul Bakker23986e52011-04-24 08:57:21 +00001374 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001375 y = ( y << biH ) | ( x >> biH );
1376 z = y / b;
1377 y -= z * b;
1378
1379 x <<= biH;
1380 y = ( y << biH ) | ( x >> biH );
1381 z = y / b;
1382 y -= z * b;
1383 }
1384
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001385 /*
1386 * If A is negative, then the current y represents a negative value.
1387 * Flipping it to the positive side.
1388 */
1389 if( A->s < 0 && y != 0 )
1390 y = b - y;
1391
Paul Bakker5121ce52009-01-03 21:22:43 +00001392 *r = y;
1393
1394 return( 0 );
1395}
1396
1397/*
1398 * Fast Montgomery initialization (thanks to Tom St Denis)
1399 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001400static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001401{
Paul Bakkera755ca12011-04-24 09:11:17 +00001402 t_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnard397858b2014-03-11 13:47:05 +01001403 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001404
1405 x = m0;
1406 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001407
Manuel Pégourié-Gonnard397858b2014-03-11 13:47:05 +01001408 for( i = biL; i >= 8; i /= 2 )
1409 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001410
1411 *mm = ~x + 1;
1412}
1413
1414/*
1415 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1416 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001417static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001418{
Paul Bakker23986e52011-04-24 08:57:21 +00001419 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001420 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001421
1422 memset( T->p, 0, T->n * ciL );
1423
1424 d = T->p;
1425 n = N->n;
1426 m = ( B->n < n ) ? B->n : n;
1427
1428 for( i = 0; i < n; i++ )
1429 {
1430 /*
1431 * T = (T + u0*B + u1*N) / 2^biL
1432 */
1433 u0 = A->p[i];
1434 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1435
1436 mpi_mul_hlp( m, B->p, d, u0 );
1437 mpi_mul_hlp( n, N->p, d, u1 );
1438
1439 *d++ = u0; d[n + 1] = 0;
1440 }
1441
1442 memcpy( A->p, d, (n + 1) * ciL );
1443
1444 if( mpi_cmp_abs( A, N ) >= 0 )
1445 mpi_sub_hlp( n, N->p, A->p );
1446 else
1447 /* prevent timing attacks */
1448 mpi_sub_hlp( n, A->p, T->p );
1449}
1450
1451/*
1452 * Montgomery reduction: A = A * R^-1 mod N
1453 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001454static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001455{
Paul Bakkera755ca12011-04-24 09:11:17 +00001456 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001457 mpi U;
1458
Paul Bakker8ddb6452013-02-27 14:56:33 +01001459 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001460 U.p = &z;
1461
1462 mpi_montmul( A, &U, N, mm, T );
1463}
1464
1465/*
1466 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1467 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001468int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001469{
Paul Bakker23986e52011-04-24 08:57:21 +00001470 int ret;
1471 size_t wbits, wsize, one = 1;
1472 size_t i, j, nblimbs;
1473 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001474 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001475 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1476 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001477
1478 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001479 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001480
Paul Bakkerf6198c12012-05-16 08:02:29 +00001481 if( mpi_cmp_int( E, 0 ) < 0 )
1482 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1483
1484 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001485 * Init temps and window size
1486 */
1487 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001488 mpi_init( &RR ); mpi_init( &T );
Manuel Pégourié-Gonnard7fd620b2014-01-18 19:05:23 +01001489 mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001490 memset( W, 0, sizeof( W ) );
1491
1492 i = mpi_msb( E );
1493
1494 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1495 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1496
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001497 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1498 wsize = POLARSSL_MPI_WINDOW_SIZE;
1499
Paul Bakker5121ce52009-01-03 21:22:43 +00001500 j = N->n + 1;
1501 MPI_CHK( mpi_grow( X, j ) );
1502 MPI_CHK( mpi_grow( &W[1], j ) );
1503 MPI_CHK( mpi_grow( &T, j * 2 ) );
1504
1505 /*
Paul Bakker50546922012-05-19 08:40:49 +00001506 * Compensate for negative A (and correct at the end)
1507 */
1508 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001509 if( neg )
1510 {
1511 MPI_CHK( mpi_copy( &Apos, A ) );
1512 Apos.s = 1;
1513 A = &Apos;
1514 }
1515
1516 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001517 * If 1st call, pre-compute R^2 mod N
1518 */
1519 if( _RR == NULL || _RR->p == NULL )
1520 {
1521 MPI_CHK( mpi_lset( &RR, 1 ) );
1522 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1523 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1524
1525 if( _RR != NULL )
1526 memcpy( _RR, &RR, sizeof( mpi ) );
1527 }
1528 else
1529 memcpy( &RR, _RR, sizeof( mpi ) );
1530
1531 /*
1532 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1533 */
1534 if( mpi_cmp_mpi( A, N ) >= 0 )
Paul Bakker1dc45f12014-01-23 20:38:35 +01001535 {
1536 MPI_CHK( mpi_mod_mpi( &W[1], A, N ) );
1537 }
1538 else
1539 MPI_CHK( mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001540
1541 mpi_montmul( &W[1], &RR, N, mm, &T );
1542
1543 /*
1544 * X = R^2 * R^-1 mod N = R mod N
1545 */
1546 MPI_CHK( mpi_copy( X, &RR ) );
1547 mpi_montred( X, N, mm, &T );
1548
1549 if( wsize > 1 )
1550 {
1551 /*
1552 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1553 */
Paul Bakker23986e52011-04-24 08:57:21 +00001554 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001555
1556 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1557 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1558
1559 for( i = 0; i < wsize - 1; i++ )
1560 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakkerc3ec63d2013-10-29 16:18:35 +01001561
Paul Bakker5121ce52009-01-03 21:22:43 +00001562 /*
1563 * W[i] = W[i - 1] * W[1]
1564 */
Paul Bakker23986e52011-04-24 08:57:21 +00001565 for( i = j + 1; i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001566 {
1567 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1568 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1569
1570 mpi_montmul( &W[i], &W[1], N, mm, &T );
1571 }
1572 }
1573
1574 nblimbs = E->n;
1575 bufsize = 0;
1576 nbits = 0;
1577 wbits = 0;
1578 state = 0;
1579
1580 while( 1 )
1581 {
1582 if( bufsize == 0 )
1583 {
Paul Bakkerc3ec63d2013-10-29 16:18:35 +01001584 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001585 break;
1586
Paul Bakkerc3ec63d2013-10-29 16:18:35 +01001587 nblimbs--;
1588
Paul Bakkera755ca12011-04-24 09:11:17 +00001589 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001590 }
1591
1592 bufsize--;
1593
1594 ei = (E->p[nblimbs] >> bufsize) & 1;
1595
1596 /*
1597 * skip leading 0s
1598 */
1599 if( ei == 0 && state == 0 )
1600 continue;
1601
1602 if( ei == 0 && state == 1 )
1603 {
1604 /*
1605 * out of window, square X
1606 */
1607 mpi_montmul( X, X, N, mm, &T );
1608 continue;
1609 }
1610
1611 /*
1612 * add ei to current window
1613 */
1614 state = 2;
1615
1616 nbits++;
1617 wbits |= (ei << (wsize - nbits));
1618
1619 if( nbits == wsize )
1620 {
1621 /*
1622 * X = X^wsize R^-1 mod N
1623 */
1624 for( i = 0; i < wsize; i++ )
1625 mpi_montmul( X, X, N, mm, &T );
1626
1627 /*
1628 * X = X * W[wbits] R^-1 mod N
1629 */
1630 mpi_montmul( X, &W[wbits], N, mm, &T );
1631
1632 state--;
1633 nbits = 0;
1634 wbits = 0;
1635 }
1636 }
1637
1638 /*
1639 * process the remaining bits
1640 */
1641 for( i = 0; i < nbits; i++ )
1642 {
1643 mpi_montmul( X, X, N, mm, &T );
1644
1645 wbits <<= 1;
1646
Paul Bakker23986e52011-04-24 08:57:21 +00001647 if( (wbits & (one << wsize)) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001648 mpi_montmul( X, &W[1], N, mm, &T );
1649 }
1650
1651 /*
1652 * X = A^E * R * R^-1 mod N = A^E mod N
1653 */
1654 mpi_montred( X, N, mm, &T );
1655
Paul Bakkerf6198c12012-05-16 08:02:29 +00001656 if( neg )
1657 {
1658 X->s = -1;
Paul Bakker1dc45f12014-01-23 20:38:35 +01001659 MPI_CHK( mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001660 }
1661
Paul Bakker5121ce52009-01-03 21:22:43 +00001662cleanup:
1663
Paul Bakker23986e52011-04-24 08:57:21 +00001664 for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001665 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001666
Paul Bakkerf6198c12012-05-16 08:02:29 +00001667 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001668
Paul Bakker6995efe2014-03-31 12:08:17 +02001669 if( _RR == NULL || _RR->p == NULL )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001670 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001671
1672 return( ret );
1673}
1674
Paul Bakker5121ce52009-01-03 21:22:43 +00001675/*
1676 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1677 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001678int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001679{
Paul Bakker23986e52011-04-24 08:57:21 +00001680 int ret;
1681 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001682 mpi TG, TA, TB;
1683
Paul Bakker6c591fa2011-05-05 11:49:20 +00001684 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001685
Paul Bakker5121ce52009-01-03 21:22:43 +00001686 MPI_CHK( mpi_copy( &TA, A ) );
1687 MPI_CHK( mpi_copy( &TB, B ) );
1688
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001689 lz = mpi_lsb( &TA );
1690 lzt = mpi_lsb( &TB );
1691
1692 if ( lzt < lz )
1693 lz = lzt;
1694
1695 MPI_CHK( mpi_shift_r( &TA, lz ) );
1696 MPI_CHK( mpi_shift_r( &TB, lz ) );
1697
Paul Bakker5121ce52009-01-03 21:22:43 +00001698 TA.s = TB.s = 1;
1699
1700 while( mpi_cmp_int( &TA, 0 ) != 0 )
1701 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001702 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1703 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001704
1705 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1706 {
1707 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1708 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1709 }
1710 else
1711 {
1712 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1713 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1714 }
1715 }
1716
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001717 MPI_CHK( mpi_shift_l( &TB, lz ) );
1718 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001719
1720cleanup:
1721
Paul Bakker6c591fa2011-05-05 11:49:20 +00001722 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001723
1724 return( ret );
1725}
1726
Paul Bakker358d3252014-04-30 16:11:39 +02001727/*
1728 * Fill X with size bytes of random.
1729 *
1730 * Use a temporary bytes representation to make sure the result is the same
1731 * regardless of the platform endianness (usefull when f_rng is actually
1732 * deterministic, eg for tests).
1733 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001734int mpi_fill_random( mpi *X, size_t size,
1735 int (*f_rng)(void *, unsigned char *, size_t),
1736 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001737{
Paul Bakker23986e52011-04-24 08:57:21 +00001738 int ret;
Paul Bakker358d3252014-04-30 16:11:39 +02001739 unsigned char buf[POLARSSL_MPI_MAX_SIZE];
1740
1741 if( size > POLARSSL_MPI_MAX_SIZE )
1742 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001743
Paul Bakker39dfdac2012-02-12 17:17:27 +00001744 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001745 MPI_CHK( mpi_lset( X, 0 ) );
1746
Paul Bakker358d3252014-04-30 16:11:39 +02001747 MPI_CHK( f_rng( p_rng, buf, size ) );
1748 MPI_CHK( mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001749
1750cleanup:
1751 return( ret );
1752}
1753
Paul Bakker5121ce52009-01-03 21:22:43 +00001754/*
1755 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1756 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001757int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001758{
1759 int ret;
1760 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1761
1762 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001763 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001764
Paul Bakker6c591fa2011-05-05 11:49:20 +00001765 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1766 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1767 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001768
1769 MPI_CHK( mpi_gcd( &G, A, N ) );
1770
1771 if( mpi_cmp_int( &G, 1 ) != 0 )
1772 {
Paul Bakker40e46942009-01-03 21:51:57 +00001773 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001774 goto cleanup;
1775 }
1776
1777 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1778 MPI_CHK( mpi_copy( &TU, &TA ) );
1779 MPI_CHK( mpi_copy( &TB, N ) );
1780 MPI_CHK( mpi_copy( &TV, N ) );
1781
1782 MPI_CHK( mpi_lset( &U1, 1 ) );
1783 MPI_CHK( mpi_lset( &U2, 0 ) );
1784 MPI_CHK( mpi_lset( &V1, 0 ) );
1785 MPI_CHK( mpi_lset( &V2, 1 ) );
1786
1787 do
1788 {
1789 while( ( TU.p[0] & 1 ) == 0 )
1790 {
1791 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1792
1793 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1794 {
1795 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1796 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1797 }
1798
1799 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1800 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1801 }
1802
1803 while( ( TV.p[0] & 1 ) == 0 )
1804 {
1805 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1806
1807 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1808 {
1809 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1810 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1811 }
1812
1813 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1814 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1815 }
1816
1817 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1818 {
1819 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1820 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1821 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1822 }
1823 else
1824 {
1825 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1826 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1827 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1828 }
1829 }
1830 while( mpi_cmp_int( &TU, 0 ) != 0 );
1831
1832 while( mpi_cmp_int( &V1, 0 ) < 0 )
1833 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1834
1835 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1836 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1837
1838 MPI_CHK( mpi_copy( X, &V1 ) );
1839
1840cleanup:
1841
Paul Bakker6c591fa2011-05-05 11:49:20 +00001842 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1843 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1844 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001845
1846 return( ret );
1847}
1848
Paul Bakkerd9374b02012-11-02 11:02:58 +00001849#if defined(POLARSSL_GENPRIME)
1850
Paul Bakker5121ce52009-01-03 21:22:43 +00001851static const int small_prime[] =
1852{
1853 3, 5, 7, 11, 13, 17, 19, 23,
1854 29, 31, 37, 41, 43, 47, 53, 59,
1855 61, 67, 71, 73, 79, 83, 89, 97,
1856 101, 103, 107, 109, 113, 127, 131, 137,
1857 139, 149, 151, 157, 163, 167, 173, 179,
1858 181, 191, 193, 197, 199, 211, 223, 227,
1859 229, 233, 239, 241, 251, 257, 263, 269,
1860 271, 277, 281, 283, 293, 307, 311, 313,
1861 317, 331, 337, 347, 349, 353, 359, 367,
1862 373, 379, 383, 389, 397, 401, 409, 419,
1863 421, 431, 433, 439, 443, 449, 457, 461,
1864 463, 467, 479, 487, 491, 499, 503, 509,
1865 521, 523, 541, 547, 557, 563, 569, 571,
1866 577, 587, 593, 599, 601, 607, 613, 617,
1867 619, 631, 641, 643, 647, 653, 659, 661,
1868 673, 677, 683, 691, 701, 709, 719, 727,
1869 733, 739, 743, 751, 757, 761, 769, 773,
1870 787, 797, 809, 811, 821, 823, 827, 829,
1871 839, 853, 857, 859, 863, 877, 881, 883,
1872 887, 907, 911, 919, 929, 937, 941, 947,
1873 953, 967, 971, 977, 983, 991, 997, -103
1874};
1875
1876/*
1877 * Miller-Rabin primality test (HAC 4.24)
1878 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001879int mpi_is_prime( mpi *X,
1880 int (*f_rng)(void *, unsigned char *, size_t),
1881 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001882{
Paul Bakker23986e52011-04-24 08:57:21 +00001883 int ret, xs;
1884 size_t i, j, n, s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001885 mpi W, R, T, A, RR;
Paul Bakker5121ce52009-01-03 21:22:43 +00001886
Paul Bakker48eab262009-06-25 21:25:49 +00001887 if( mpi_cmp_int( X, 0 ) == 0 ||
1888 mpi_cmp_int( X, 1 ) == 0 )
1889 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1890
1891 if( mpi_cmp_int( X, 2 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001892 return( 0 );
1893
Paul Bakker6c591fa2011-05-05 11:49:20 +00001894 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
1895 mpi_init( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001896
1897 xs = X->s; X->s = 1;
1898
1899 /*
1900 * test trivial factors first
1901 */
1902 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001903 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001904
1905 for( i = 0; small_prime[i] > 0; i++ )
1906 {
Paul Bakkera755ca12011-04-24 09:11:17 +00001907 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001908
1909 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
1910 return( 0 );
1911
1912 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1913
1914 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001915 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001916 }
1917
1918 /*
1919 * W = |X| - 1
1920 * R = W >> lsb( W )
1921 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001922 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001923 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001924 MPI_CHK( mpi_copy( &R, &W ) );
1925 MPI_CHK( mpi_shift_r( &R, s ) );
1926
1927 i = mpi_msb( X );
1928 /*
1929 * HAC, table 4.4
1930 */
1931 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1932 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1933 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1934
1935 for( i = 0; i < n; i++ )
1936 {
1937 /*
1938 * pick a random A, 1 < A < |X| - 1
1939 */
Paul Bakker901c6562012-04-20 13:25:38 +00001940 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001941
Paul Bakkerb94081b2011-01-05 15:53:06 +00001942 if( mpi_cmp_mpi( &A, &W ) >= 0 )
1943 {
1944 j = mpi_msb( &A ) - mpi_msb( &W );
1945 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1946 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001947 A.p[0] |= 3;
1948
1949 /*
1950 * A = A^R mod |X|
1951 */
1952 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1953
1954 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1955 mpi_cmp_int( &A, 1 ) == 0 )
1956 continue;
1957
1958 j = 1;
1959 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1960 {
1961 /*
1962 * A = A * A mod |X|
1963 */
1964 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1965 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1966
1967 if( mpi_cmp_int( &A, 1 ) == 0 )
1968 break;
1969
1970 j++;
1971 }
1972
1973 /*
1974 * not prime if A != |X| - 1 or A == 1
1975 */
1976 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1977 mpi_cmp_int( &A, 1 ) == 0 )
1978 {
Paul Bakker40e46942009-01-03 21:51:57 +00001979 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001980 break;
1981 }
1982 }
1983
1984cleanup:
1985
1986 X->s = xs;
1987
Paul Bakker6c591fa2011-05-05 11:49:20 +00001988 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
1989 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001990
1991 return( ret );
1992}
1993
1994/*
1995 * Prime number generation
1996 */
Paul Bakker23986e52011-04-24 08:57:21 +00001997int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001998 int (*f_rng)(void *, unsigned char *, size_t),
1999 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002000{
Paul Bakker23986e52011-04-24 08:57:21 +00002001 int ret;
2002 size_t k, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00002003 mpi Y;
2004
Paul Bakkerfe3256e2011-11-25 12:11:43 +00002005 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00002006 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002007
Paul Bakker6c591fa2011-05-05 11:49:20 +00002008 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002009
2010 n = BITS_TO_LIMBS( nbits );
2011
Paul Bakker901c6562012-04-20 13:25:38 +00002012 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002013
2014 k = mpi_msb( X );
2015 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
2016 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
2017
2018 X->p[0] |= 3;
2019
2020 if( dh_flag == 0 )
2021 {
2022 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
2023 {
Paul Bakker40e46942009-01-03 21:51:57 +00002024 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002025 goto cleanup;
2026
2027 MPI_CHK( mpi_add_int( X, X, 2 ) );
2028 }
2029 }
2030 else
2031 {
2032 MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
2033 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2034
2035 while( 1 )
2036 {
2037 if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
2038 {
2039 if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
2040 break;
2041
Paul Bakker40e46942009-01-03 21:51:57 +00002042 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002043 goto cleanup;
2044 }
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 MPI_CHK( mpi_add_int( &Y, X, 1 ) );
2050 MPI_CHK( mpi_add_int( X, X, 2 ) );
2051 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2052 }
2053 }
2054
2055cleanup:
2056
Paul Bakker6c591fa2011-05-05 11:49:20 +00002057 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002058
2059 return( ret );
2060}
2061
2062#endif
2063
Paul Bakker40e46942009-01-03 21:51:57 +00002064#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002065
Paul Bakker23986e52011-04-24 08:57:21 +00002066#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002067
2068static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2069{
2070 { 693, 609, 21 },
2071 { 1764, 868, 28 },
2072 { 768454923, 542167814, 1 }
2073};
2074
Paul Bakker5121ce52009-01-03 21:22:43 +00002075/*
2076 * Checkup routine
2077 */
2078int mpi_self_test( int verbose )
2079{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002080 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002081 mpi A, E, N, X, Y, U, V;
2082
Paul Bakker6c591fa2011-05-05 11:49:20 +00002083 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2084 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002085
2086 MPI_CHK( mpi_read_string( &A, 16,
2087 "EFE021C2645FD1DC586E69184AF4A31E" \
2088 "D5F53E93B5F123FA41680867BA110131" \
2089 "944FE7952E2517337780CB0DB80E61AA" \
2090 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2091
2092 MPI_CHK( mpi_read_string( &E, 16,
2093 "B2E7EFD37075B9F03FF989C7C5051C20" \
2094 "34D2A323810251127E7BF8625A4F49A5" \
2095 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2096 "5B5C25763222FEFCCFC38B832366C29E" ) );
2097
2098 MPI_CHK( mpi_read_string( &N, 16,
2099 "0066A198186C18C10B2F5ED9B522752A" \
2100 "9830B69916E535C8F047518A889A43A5" \
2101 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2102
2103 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2104
2105 MPI_CHK( mpi_read_string( &U, 16,
2106 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2107 "9E857EA95A03512E2BAE7391688D264A" \
2108 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2109 "8001B72E848A38CAE1C65F78E56ABDEF" \
2110 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2111 "ECF677152EF804370C1A305CAF3B5BF1" \
2112 "30879B56C61DE584A0F53A2447A51E" ) );
2113
2114 if( verbose != 0 )
2115 printf( " MPI test #1 (mul_mpi): " );
2116
2117 if( mpi_cmp_mpi( &X, &U ) != 0 )
2118 {
2119 if( verbose != 0 )
2120 printf( "failed\n" );
2121
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002122 ret = 1;
2123 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002124 }
2125
2126 if( verbose != 0 )
2127 printf( "passed\n" );
2128
2129 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2130
2131 MPI_CHK( mpi_read_string( &U, 16,
2132 "256567336059E52CAE22925474705F39A94" ) );
2133
2134 MPI_CHK( mpi_read_string( &V, 16,
2135 "6613F26162223DF488E9CD48CC132C7A" \
2136 "0AC93C701B001B092E4E5B9F73BCD27B" \
2137 "9EE50D0657C77F374E903CDFA4C642" ) );
2138
2139 if( verbose != 0 )
2140 printf( " MPI test #2 (div_mpi): " );
2141
2142 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2143 mpi_cmp_mpi( &Y, &V ) != 0 )
2144 {
2145 if( verbose != 0 )
2146 printf( "failed\n" );
2147
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002148 ret = 1;
2149 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002150 }
2151
2152 if( verbose != 0 )
2153 printf( "passed\n" );
2154
2155 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2156
2157 MPI_CHK( mpi_read_string( &U, 16,
2158 "36E139AEA55215609D2816998ED020BB" \
2159 "BD96C37890F65171D948E9BC7CBAA4D9" \
2160 "325D24D6A3C12710F10A09FA08AB87" ) );
2161
2162 if( verbose != 0 )
2163 printf( " MPI test #3 (exp_mod): " );
2164
2165 if( mpi_cmp_mpi( &X, &U ) != 0 )
2166 {
2167 if( verbose != 0 )
2168 printf( "failed\n" );
2169
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002170 ret = 1;
2171 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002172 }
2173
2174 if( verbose != 0 )
2175 printf( "passed\n" );
2176
Paul Bakker5690efc2011-05-26 13:16:06 +00002177#if defined(POLARSSL_GENPRIME)
Paul Bakker5121ce52009-01-03 21:22:43 +00002178 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2179
2180 MPI_CHK( mpi_read_string( &U, 16,
2181 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2182 "C3DBA76456363A10869622EAC2DD84EC" \
2183 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2184
2185 if( verbose != 0 )
2186 printf( " MPI test #4 (inv_mod): " );
2187
2188 if( mpi_cmp_mpi( &X, &U ) != 0 )
2189 {
2190 if( verbose != 0 )
2191 printf( "failed\n" );
2192
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002193 ret = 1;
2194 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002195 }
2196
2197 if( verbose != 0 )
2198 printf( "passed\n" );
Paul Bakker5690efc2011-05-26 13:16:06 +00002199#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002200
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002201 if( verbose != 0 )
2202 printf( " MPI test #5 (simple gcd): " );
2203
2204 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2205 {
2206 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002207 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002208
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002209 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002210
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002211 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2212 {
2213 if( verbose != 0 )
2214 printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002215
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002216 ret = 1;
2217 goto cleanup;
2218 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002219 }
2220
2221 if( verbose != 0 )
2222 printf( "passed\n" );
2223
Paul Bakker5121ce52009-01-03 21:22:43 +00002224cleanup:
2225
2226 if( ret != 0 && verbose != 0 )
2227 printf( "Unexpected error, return code = %08X\n", ret );
2228
Paul Bakker6c591fa2011-05-05 11:49:20 +00002229 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2230 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002231
2232 if( verbose != 0 )
2233 printf( "\n" );
2234
2235 return( ret );
2236}
2237
2238#endif
2239
2240#endif