blob: 14a3dc7cfc8629febb1db7c3e093efaca4a8d258 [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 */
22/*
23 * This MPI implementation is based on:
24 *
25 * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
26 * http://www.stillhq.com/extracted/gnupg-api/mpi/
27 * http://math.libtomcrypt.com/files/tommath.pdf
28 */
29
Paul Bakker40e46942009-01-03 21:51:57 +000030#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000031
Paul Bakker40e46942009-01-03 21:51:57 +000032#if defined(POLARSSL_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000033
Paul Bakker40e46942009-01-03 21:51:57 +000034#include "polarssl/bignum.h"
35#include "polarssl/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000036
Paul Bakker5121ce52009-01-03 21:22:43 +000037#include <stdlib.h>
Paul Bakker5121ce52009-01-03 21:22:43 +000038
Paul Bakker312da332014-06-13 17:20:13 +020039/* Implementation that should never be optimized out by the compiler */
40static void polarssl_zeroize( void *v, size_t n ) {
41 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
42}
43
Paul Bakkerf9688572011-05-05 10:00:45 +000044#define ciL (sizeof(t_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000045#define biL (ciL << 3) /* bits in limb */
46#define biH (ciL << 2) /* half limb size */
47
Manuel Pégourié-Gonnard42571dd2015-10-05 15:23:11 +010048#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
49
Paul Bakker5121ce52009-01-03 21:22:43 +000050/*
51 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard9b753052015-09-28 13:48:04 +020052 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000053 */
Manuel Pégourié-Gonnard9b753052015-09-28 13:48:04 +020054#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
55#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000056
57/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000058 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000059 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000060void mpi_init( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000061{
Paul Bakker6c591fa2011-05-05 11:49:20 +000062 if( X == NULL )
63 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000064
Paul Bakker6c591fa2011-05-05 11:49:20 +000065 X->s = 1;
66 X->n = 0;
67 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000068}
69
70/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000071 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000072 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000073void mpi_free( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000074{
Paul Bakker6c591fa2011-05-05 11:49:20 +000075 if( X == NULL )
76 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000077
Paul Bakker6c591fa2011-05-05 11:49:20 +000078 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +000079 {
Paul Bakker312da332014-06-13 17:20:13 +020080 polarssl_zeroize( X->p, X->n * ciL );
Paul Bakker6c591fa2011-05-05 11:49:20 +000081 free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +000082 }
83
Paul Bakker6c591fa2011-05-05 11:49:20 +000084 X->s = 1;
85 X->n = 0;
86 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000087}
88
89/*
90 * Enlarge to the specified number of limbs
91 */
Paul Bakker23986e52011-04-24 08:57:21 +000092int mpi_grow( mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +000093{
Paul Bakkera755ca12011-04-24 09:11:17 +000094 t_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +000095
Paul Bakkerf9688572011-05-05 10:00:45 +000096 if( nblimbs > POLARSSL_MPI_MAX_LIMBS )
Paul Bakker69e095c2011-12-10 21:55:01 +000097 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +000098
Paul Bakker5121ce52009-01-03 21:22:43 +000099 if( X->n < nblimbs )
100 {
Paul Bakkera755ca12011-04-24 09:11:17 +0000101 if( ( p = (t_uint *) malloc( nblimbs * ciL ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000102 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000103
104 memset( p, 0, nblimbs * ciL );
105
106 if( X->p != NULL )
107 {
108 memcpy( p, X->p, X->n * ciL );
Paul Bakker312da332014-06-13 17:20:13 +0200109 polarssl_zeroize( X->p, X->n * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000110 free( X->p );
111 }
112
113 X->n = nblimbs;
114 X->p = p;
115 }
116
117 return( 0 );
118}
119
120/*
121 * Copy the contents of Y into X
122 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000123int mpi_copy( mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000124{
Paul Bakker23986e52011-04-24 08:57:21 +0000125 int ret;
126 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000127
128 if( X == Y )
129 return( 0 );
130
131 for( i = Y->n - 1; i > 0; i-- )
132 if( Y->p[i] != 0 )
133 break;
134 i++;
135
136 X->s = Y->s;
137
138 MPI_CHK( mpi_grow( X, i ) );
139
140 memset( X->p, 0, X->n * ciL );
141 memcpy( X->p, Y->p, i * ciL );
142
143cleanup:
144
145 return( ret );
146}
147
148/*
149 * Swap the contents of X and Y
150 */
151void mpi_swap( mpi *X, mpi *Y )
152{
153 mpi T;
154
155 memcpy( &T, X, sizeof( mpi ) );
156 memcpy( X, Y, sizeof( mpi ) );
157 memcpy( Y, &T, sizeof( mpi ) );
158}
159
160/*
161 * Set value from integer
162 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000163int mpi_lset( mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000164{
165 int ret;
166
167 MPI_CHK( mpi_grow( X, 1 ) );
168 memset( X->p, 0, X->n * ciL );
169
170 X->p[0] = ( z < 0 ) ? -z : z;
171 X->s = ( z < 0 ) ? -1 : 1;
172
173cleanup:
174
175 return( ret );
176}
177
178/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000179 * Get a specific bit
180 */
Paul Bakker6b906e52012-05-08 12:01:43 +0000181int mpi_get_bit( const mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000182{
183 if( X->n * biL <= pos )
184 return( 0 );
185
186 return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
187}
188
189/*
190 * Set a bit to a specific value of 0 or 1
191 */
192int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
193{
194 int ret = 0;
195 size_t off = pos / biL;
196 size_t idx = pos % biL;
197
198 if( val != 0 && val != 1 )
199 return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
200
201 if( X->n * biL <= pos )
202 {
203 if( val == 0 )
204 return ( 0 );
205
206 MPI_CHK( mpi_grow( X, off + 1 ) );
207 }
208
209 X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
210
211cleanup:
212
213 return( ret );
214}
215
216/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000217 * Return the number of least significant bits
218 */
Paul Bakker23986e52011-04-24 08:57:21 +0000219size_t mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000220{
Paul Bakker23986e52011-04-24 08:57:21 +0000221 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
223 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000224 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000225 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
226 return( count );
227
228 return( 0 );
229}
230
231/*
232 * Return the number of most significant bits
233 */
Paul Bakker23986e52011-04-24 08:57:21 +0000234size_t mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000235{
Paul Bakker23986e52011-04-24 08:57:21 +0000236 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000237
238 for( i = X->n - 1; i > 0; i-- )
239 if( X->p[i] != 0 )
240 break;
241
Paul Bakker23986e52011-04-24 08:57:21 +0000242 for( j = biL; j > 0; j-- )
243 if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000244 break;
245
Paul Bakker23986e52011-04-24 08:57:21 +0000246 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000247}
248
249/*
250 * Return the total size in bytes
251 */
Paul Bakker23986e52011-04-24 08:57:21 +0000252size_t mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000253{
254 return( ( mpi_msb( X ) + 7 ) >> 3 );
255}
256
257/*
258 * Convert an ASCII character to digit value
259 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000260static int mpi_get_digit( t_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000261{
262 *d = 255;
263
264 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
265 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
266 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
267
Paul Bakkera755ca12011-04-24 09:11:17 +0000268 if( *d >= (t_uint) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000269 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000270
271 return( 0 );
272}
273
274/*
275 * Import from an ASCII string
276 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000277int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000278{
Paul Bakker23986e52011-04-24 08:57:21 +0000279 int ret;
280 size_t i, j, slen, n;
Paul Bakkera755ca12011-04-24 09:11:17 +0000281 t_uint d;
Paul Bakker5121ce52009-01-03 21:22:43 +0000282 mpi T;
283
284 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000285 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000286
Paul Bakker6c591fa2011-05-05 11:49:20 +0000287 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000288
Paul Bakkerff60ee62010-03-16 21:09:09 +0000289 slen = strlen( s );
290
Paul Bakker5121ce52009-01-03 21:22:43 +0000291 if( radix == 16 )
292 {
Manuel Pégourié-Gonnard42571dd2015-10-05 15:23:11 +0100293 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard9b753052015-09-28 13:48:04 +0200294 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
295
Paul Bakkerff60ee62010-03-16 21:09:09 +0000296 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000297
298 MPI_CHK( mpi_grow( X, n ) );
299 MPI_CHK( mpi_lset( X, 0 ) );
300
Paul Bakker23986e52011-04-24 08:57:21 +0000301 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000302 {
Paul Bakker23986e52011-04-24 08:57:21 +0000303 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000304 {
305 X->s = -1;
306 break;
307 }
308
Paul Bakker23986e52011-04-24 08:57:21 +0000309 MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000310 X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
311 }
312 }
313 else
314 {
315 MPI_CHK( mpi_lset( X, 0 ) );
316
Paul Bakkerff60ee62010-03-16 21:09:09 +0000317 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000318 {
319 if( i == 0 && s[i] == '-' )
320 {
321 X->s = -1;
322 continue;
323 }
324
325 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
326 MPI_CHK( mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000327
328 if( X->s == 1 )
329 {
330 MPI_CHK( mpi_add_int( X, &T, d ) );
331 }
332 else
333 {
334 MPI_CHK( mpi_sub_int( X, &T, d ) );
335 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000336 }
337 }
338
339cleanup:
340
Paul Bakker6c591fa2011-05-05 11:49:20 +0000341 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000342
343 return( ret );
344}
345
346/*
347 * Helper to write the digits high-order first
348 */
349static int mpi_write_hlp( mpi *X, int radix, char **p )
350{
351 int ret;
Paul Bakkera755ca12011-04-24 09:11:17 +0000352 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000353
354 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000355 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000356
357 MPI_CHK( mpi_mod_int( &r, X, radix ) );
358 MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
359
360 if( mpi_cmp_int( X, 0 ) != 0 )
361 MPI_CHK( mpi_write_hlp( X, radix, p ) );
362
363 if( r < 10 )
364 *(*p)++ = (char)( r + 0x30 );
365 else
366 *(*p)++ = (char)( r + 0x37 );
367
368cleanup:
369
370 return( ret );
371}
372
373/*
374 * Export into an ASCII string
375 */
Paul Bakker23986e52011-04-24 08:57:21 +0000376int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000377{
Paul Bakker23986e52011-04-24 08:57:21 +0000378 int ret = 0;
379 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000380 char *p;
381 mpi T;
382
383 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000384 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000385
386 n = mpi_msb( X );
387 if( radix >= 4 ) n >>= 1;
388 if( radix >= 16 ) n >>= 1;
389 n += 3;
390
391 if( *slen < n )
392 {
393 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000394 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000395 }
396
397 p = s;
Paul Bakker6c591fa2011-05-05 11:49:20 +0000398 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000399
400 if( X->s == -1 )
401 *p++ = '-';
402
403 if( radix == 16 )
404 {
Paul Bakker23986e52011-04-24 08:57:21 +0000405 int c;
406 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000407
Paul Bakker23986e52011-04-24 08:57:21 +0000408 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000409 {
Paul Bakker23986e52011-04-24 08:57:21 +0000410 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000411 {
Paul Bakker23986e52011-04-24 08:57:21 +0000412 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000413
Paul Bakker23986e52011-04-24 08:57:21 +0000414 if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000415 continue;
416
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000417 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000418 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000419 k = 1;
420 }
421 }
422 }
423 else
424 {
425 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000426
427 if( T.s == -1 )
428 T.s = 1;
429
Paul Bakker5121ce52009-01-03 21:22:43 +0000430 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
431 }
432
433 *p++ = '\0';
434 *slen = p - s;
435
436cleanup:
437
Paul Bakker6c591fa2011-05-05 11:49:20 +0000438 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000439
440 return( ret );
441}
442
Paul Bakker335db3f2011-04-25 15:28:35 +0000443#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000444/*
445 * Read X from an opened file
446 */
447int mpi_read_file( mpi *X, int radix, FILE *fin )
448{
Paul Bakkera755ca12011-04-24 09:11:17 +0000449 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000450 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000451 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000452 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000453 * Buffer should have space for (short) label and decimal formatted MPI,
454 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000455 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000456 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000457
458 memset( s, 0, sizeof( s ) );
459 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000460 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000461
462 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000463 if( slen == sizeof( s ) - 2 )
464 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
465
Paul Bakker5121ce52009-01-03 21:22:43 +0000466 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
467 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
468
469 p = s + slen;
470 while( --p >= s )
471 if( mpi_get_digit( &d, radix, *p ) != 0 )
472 break;
473
474 return( mpi_read_string( X, radix, p + 1 ) );
475}
476
477/*
478 * Write X into an opened file (or stdout if fout == NULL)
479 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000480int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000481{
Paul Bakker23986e52011-04-24 08:57:21 +0000482 int ret;
483 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000484 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000485 * Buffer should have space for (short) label and decimal formatted MPI,
486 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000487 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000488 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000489
490 n = sizeof( s );
491 memset( s, 0, n );
492 n -= 2;
493
Paul Bakker23986e52011-04-24 08:57:21 +0000494 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000495
496 if( p == NULL ) p = "";
497
498 plen = strlen( p );
499 slen = strlen( s );
500 s[slen++] = '\r';
501 s[slen++] = '\n';
502
503 if( fout != NULL )
504 {
505 if( fwrite( p, 1, plen, fout ) != plen ||
506 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000507 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000508 }
509 else
510 printf( "%s%s", p, s );
511
512cleanup:
513
514 return( ret );
515}
Paul Bakker335db3f2011-04-25 15:28:35 +0000516#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000517
518/*
519 * Import X from unsigned binary data, big endian
520 */
Paul Bakker23986e52011-04-24 08:57:21 +0000521int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000522{
Paul Bakker23986e52011-04-24 08:57:21 +0000523 int ret;
524 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000525
526 for( n = 0; n < buflen; n++ )
527 if( buf[n] != 0 )
528 break;
529
530 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
531 MPI_CHK( mpi_lset( X, 0 ) );
532
Paul Bakker23986e52011-04-24 08:57:21 +0000533 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000534 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000535
536cleanup:
537
538 return( ret );
539}
540
541/*
542 * Export X into unsigned binary data, big endian
543 */
Paul Bakker23986e52011-04-24 08:57:21 +0000544int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000545{
Paul Bakker23986e52011-04-24 08:57:21 +0000546 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000547
548 n = mpi_size( X );
549
550 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000551 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000552
553 memset( buf, 0, buflen );
554
555 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
556 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
557
558 return( 0 );
559}
560
561/*
562 * Left-shift: X <<= count
563 */
Paul Bakker23986e52011-04-24 08:57:21 +0000564int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000565{
Paul Bakker23986e52011-04-24 08:57:21 +0000566 int ret;
567 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000568 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000569
570 v0 = count / (biL );
571 t1 = count & (biL - 1);
572
573 i = mpi_msb( X ) + count;
574
Paul Bakkerf9688572011-05-05 10:00:45 +0000575 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000576 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
577
578 ret = 0;
579
580 /*
581 * shift by count / limb_size
582 */
583 if( v0 > 0 )
584 {
Paul Bakker23986e52011-04-24 08:57:21 +0000585 for( i = X->n; i > v0; i-- )
586 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000587
Paul Bakker23986e52011-04-24 08:57:21 +0000588 for( ; i > 0; i-- )
589 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000590 }
591
592 /*
593 * shift by count % limb_size
594 */
595 if( t1 > 0 )
596 {
597 for( i = v0; i < X->n; i++ )
598 {
599 r1 = X->p[i] >> (biL - t1);
600 X->p[i] <<= t1;
601 X->p[i] |= r0;
602 r0 = r1;
603 }
604 }
605
606cleanup:
607
608 return( ret );
609}
610
611/*
612 * Right-shift: X >>= count
613 */
Paul Bakker23986e52011-04-24 08:57:21 +0000614int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000615{
Paul Bakker23986e52011-04-24 08:57:21 +0000616 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000617 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000618
619 v0 = count / biL;
620 v1 = count & (biL - 1);
621
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100622 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
623 return mpi_lset( X, 0 );
624
Paul Bakker5121ce52009-01-03 21:22:43 +0000625 /*
626 * shift by count / limb_size
627 */
628 if( v0 > 0 )
629 {
630 for( i = 0; i < X->n - v0; i++ )
631 X->p[i] = X->p[i + v0];
632
633 for( ; i < X->n; i++ )
634 X->p[i] = 0;
635 }
636
637 /*
638 * shift by count % limb_size
639 */
640 if( v1 > 0 )
641 {
Paul Bakker23986e52011-04-24 08:57:21 +0000642 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000643 {
Paul Bakker23986e52011-04-24 08:57:21 +0000644 r1 = X->p[i - 1] << (biL - v1);
645 X->p[i - 1] >>= v1;
646 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000647 r0 = r1;
648 }
649 }
650
651 return( 0 );
652}
653
654/*
655 * Compare unsigned values
656 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000657int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000658{
Paul Bakker23986e52011-04-24 08:57:21 +0000659 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000660
Paul Bakker23986e52011-04-24 08:57:21 +0000661 for( i = X->n; i > 0; i-- )
662 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000663 break;
664
Paul Bakker23986e52011-04-24 08:57:21 +0000665 for( j = Y->n; j > 0; j-- )
666 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000667 break;
668
Paul Bakker23986e52011-04-24 08:57:21 +0000669 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000670 return( 0 );
671
672 if( i > j ) return( 1 );
673 if( j > i ) return( -1 );
674
Paul Bakker23986e52011-04-24 08:57:21 +0000675 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000676 {
Paul Bakker23986e52011-04-24 08:57:21 +0000677 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
678 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000679 }
680
681 return( 0 );
682}
683
684/*
685 * Compare signed values
686 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000687int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000688{
Paul Bakker23986e52011-04-24 08:57:21 +0000689 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000690
Paul Bakker23986e52011-04-24 08:57:21 +0000691 for( i = X->n; i > 0; i-- )
692 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000693 break;
694
Paul Bakker23986e52011-04-24 08:57:21 +0000695 for( j = Y->n; j > 0; j-- )
696 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000697 break;
698
Paul Bakker23986e52011-04-24 08:57:21 +0000699 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000700 return( 0 );
701
702 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000703 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000704
705 if( X->s > 0 && Y->s < 0 ) return( 1 );
706 if( Y->s > 0 && X->s < 0 ) return( -1 );
707
Paul Bakker23986e52011-04-24 08:57:21 +0000708 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000709 {
Paul Bakker23986e52011-04-24 08:57:21 +0000710 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
711 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000712 }
713
714 return( 0 );
715}
716
717/*
718 * Compare signed values
719 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000720int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000721{
722 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000723 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000724
725 *p = ( z < 0 ) ? -z : z;
726 Y.s = ( z < 0 ) ? -1 : 1;
727 Y.n = 1;
728 Y.p = p;
729
730 return( mpi_cmp_mpi( X, &Y ) );
731}
732
733/*
734 * Unsigned addition: X = |A| + |B| (HAC 14.7)
735 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000736int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000737{
Paul Bakker23986e52011-04-24 08:57:21 +0000738 int ret;
739 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000740 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000741
742 if( X == B )
743 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000744 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000745 }
746
747 if( X != A )
748 MPI_CHK( mpi_copy( X, A ) );
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000749
750 /*
751 * X should always be positive as a result of unsigned additions.
752 */
753 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000754
Paul Bakker23986e52011-04-24 08:57:21 +0000755 for( j = B->n; j > 0; j-- )
756 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000757 break;
758
Paul Bakker23986e52011-04-24 08:57:21 +0000759 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000760
761 o = B->p; p = X->p; c = 0;
762
Paul Bakker23986e52011-04-24 08:57:21 +0000763 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000764 {
765 *p += c; c = ( *p < c );
766 *p += *o; c += ( *p < *o );
767 }
768
769 while( c != 0 )
770 {
771 if( i >= X->n )
772 {
773 MPI_CHK( mpi_grow( X, i + 1 ) );
774 p = X->p + i;
775 }
776
Paul Bakker2d319fd2012-09-16 21:34:26 +0000777 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000778 }
779
780cleanup:
781
782 return( ret );
783}
784
785/*
786 * Helper for mpi substraction
787 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000788static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000789{
Paul Bakker23986e52011-04-24 08:57:21 +0000790 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000791 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000792
793 for( i = c = 0; i < n; i++, s++, d++ )
794 {
795 z = ( *d < c ); *d -= c;
796 c = ( *d < *s ) + z; *d -= *s;
797 }
798
799 while( c != 0 )
800 {
801 z = ( *d < c ); *d -= c;
802 c = z; i++; d++;
803 }
804}
805
806/*
807 * Unsigned substraction: X = |A| - |B| (HAC 14.9)
808 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000809int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000810{
811 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000812 int ret;
813 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000814
815 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000816 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000817
Paul Bakker6c591fa2011-05-05 11:49:20 +0000818 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000819
820 if( X == B )
821 {
822 MPI_CHK( mpi_copy( &TB, B ) );
823 B = &TB;
824 }
825
826 if( X != A )
827 MPI_CHK( mpi_copy( X, A ) );
828
Paul Bakker1ef7a532009-06-20 10:50:55 +0000829 /*
830 * X should always be positive as a result of unsigned substractions.
831 */
832 X->s = 1;
833
Paul Bakker5121ce52009-01-03 21:22:43 +0000834 ret = 0;
835
Paul Bakker23986e52011-04-24 08:57:21 +0000836 for( n = B->n; n > 0; n-- )
837 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000838 break;
839
Paul Bakker23986e52011-04-24 08:57:21 +0000840 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000841
842cleanup:
843
Paul Bakker6c591fa2011-05-05 11:49:20 +0000844 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000845
846 return( ret );
847}
848
849/*
850 * Signed addition: X = A + B
851 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000852int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000853{
854 int ret, s = A->s;
855
856 if( A->s * B->s < 0 )
857 {
858 if( mpi_cmp_abs( A, B ) >= 0 )
859 {
860 MPI_CHK( mpi_sub_abs( X, A, B ) );
861 X->s = s;
862 }
863 else
864 {
865 MPI_CHK( mpi_sub_abs( X, B, A ) );
866 X->s = -s;
867 }
868 }
869 else
870 {
871 MPI_CHK( mpi_add_abs( X, A, B ) );
872 X->s = s;
873 }
874
875cleanup:
876
877 return( ret );
878}
879
880/*
881 * Signed substraction: X = A - B
882 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000883int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000884{
885 int ret, s = A->s;
886
887 if( A->s * B->s > 0 )
888 {
889 if( mpi_cmp_abs( A, B ) >= 0 )
890 {
891 MPI_CHK( mpi_sub_abs( X, A, B ) );
892 X->s = s;
893 }
894 else
895 {
896 MPI_CHK( mpi_sub_abs( X, B, A ) );
897 X->s = -s;
898 }
899 }
900 else
901 {
902 MPI_CHK( mpi_add_abs( X, A, B ) );
903 X->s = s;
904 }
905
906cleanup:
907
908 return( ret );
909}
910
911/*
912 * Signed addition: X = A + b
913 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000914int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000915{
916 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000917 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000918
919 p[0] = ( b < 0 ) ? -b : b;
920 _B.s = ( b < 0 ) ? -1 : 1;
921 _B.n = 1;
922 _B.p = p;
923
924 return( mpi_add_mpi( X, A, &_B ) );
925}
926
927/*
928 * Signed substraction: X = A - b
929 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000930int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000931{
932 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000933 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000934
935 p[0] = ( b < 0 ) ? -b : b;
936 _B.s = ( b < 0 ) ? -1 : 1;
937 _B.n = 1;
938 _B.p = p;
939
940 return( mpi_sub_mpi( X, A, &_B ) );
941}
942
943/*
944 * Helper for mpi multiplication
Paul Bakker52b845b2013-06-14 11:36:56 +0200945 */
946static
947#if defined(__APPLE__) && defined(__arm__)
948/*
949 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
950 * appears to need this to prevent bad ARM code generation at -O3.
951 */
952__attribute__ ((noinline))
953#endif
954void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000955{
Paul Bakkera755ca12011-04-24 09:11:17 +0000956 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000957
958#if defined(MULADDC_HUIT)
959 for( ; i >= 8; i -= 8 )
960 {
961 MULADDC_INIT
962 MULADDC_HUIT
963 MULADDC_STOP
964 }
965
966 for( ; i > 0; i-- )
967 {
968 MULADDC_INIT
969 MULADDC_CORE
970 MULADDC_STOP
971 }
972#else
973 for( ; i >= 16; i -= 16 )
974 {
975 MULADDC_INIT
976 MULADDC_CORE MULADDC_CORE
977 MULADDC_CORE MULADDC_CORE
978 MULADDC_CORE MULADDC_CORE
979 MULADDC_CORE MULADDC_CORE
980
981 MULADDC_CORE MULADDC_CORE
982 MULADDC_CORE MULADDC_CORE
983 MULADDC_CORE MULADDC_CORE
984 MULADDC_CORE MULADDC_CORE
985 MULADDC_STOP
986 }
987
988 for( ; i >= 8; i -= 8 )
989 {
990 MULADDC_INIT
991 MULADDC_CORE MULADDC_CORE
992 MULADDC_CORE MULADDC_CORE
993
994 MULADDC_CORE MULADDC_CORE
995 MULADDC_CORE MULADDC_CORE
996 MULADDC_STOP
997 }
998
999 for( ; i > 0; i-- )
1000 {
1001 MULADDC_INIT
1002 MULADDC_CORE
1003 MULADDC_STOP
1004 }
1005#endif
1006
1007 t++;
1008
1009 do {
1010 *d += c; c = ( *d < c ); d++;
1011 }
1012 while( c != 0 );
1013}
1014
1015/*
1016 * Baseline multiplication: X = A * B (HAC 14.12)
1017 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001018int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001019{
Paul Bakker23986e52011-04-24 08:57:21 +00001020 int ret;
1021 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001022 mpi TA, TB;
1023
Paul Bakker6c591fa2011-05-05 11:49:20 +00001024 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001025
1026 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1027 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1028
Paul Bakker23986e52011-04-24 08:57:21 +00001029 for( i = A->n; i > 0; i-- )
1030 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001031 break;
1032
Paul Bakker23986e52011-04-24 08:57:21 +00001033 for( j = B->n; j > 0; j-- )
1034 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001035 break;
1036
Paul Bakker23986e52011-04-24 08:57:21 +00001037 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001038 MPI_CHK( mpi_lset( X, 0 ) );
1039
Paul Bakker23986e52011-04-24 08:57:21 +00001040 for( i++; j > 0; j-- )
1041 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001042
1043 X->s = A->s * B->s;
1044
1045cleanup:
1046
Paul Bakker6c591fa2011-05-05 11:49:20 +00001047 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001048
1049 return( ret );
1050}
1051
1052/*
1053 * Baseline multiplication: X = A * b
1054 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001055int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001056{
1057 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001058 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001059
1060 _B.s = 1;
1061 _B.n = 1;
1062 _B.p = p;
1063 p[0] = b;
1064
1065 return( mpi_mul_mpi( X, A, &_B ) );
1066}
1067
1068/*
1069 * Division by mpi: A = Q * B + R (HAC 14.20)
1070 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001071int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001072{
Paul Bakker23986e52011-04-24 08:57:21 +00001073 int ret;
1074 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001075 mpi X, Y, Z, T1, T2;
1076
1077 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001078 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001079
Paul Bakker6c591fa2011-05-05 11:49:20 +00001080 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1081 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001082
1083 if( mpi_cmp_abs( A, B ) < 0 )
1084 {
1085 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1086 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1087 return( 0 );
1088 }
1089
1090 MPI_CHK( mpi_copy( &X, A ) );
1091 MPI_CHK( mpi_copy( &Y, B ) );
1092 X.s = Y.s = 1;
1093
1094 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1095 MPI_CHK( mpi_lset( &Z, 0 ) );
1096 MPI_CHK( mpi_grow( &T1, 2 ) );
1097 MPI_CHK( mpi_grow( &T2, 3 ) );
1098
1099 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001100 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001101 {
1102 k = biL - 1 - k;
1103 MPI_CHK( mpi_shift_l( &X, k ) );
1104 MPI_CHK( mpi_shift_l( &Y, k ) );
1105 }
1106 else k = 0;
1107
1108 n = X.n - 1;
1109 t = Y.n - 1;
Paul Bakkerc110d022012-10-19 12:15:08 +00001110 MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001111
1112 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1113 {
1114 Z.p[n - t]++;
Paul Bakker78e81962013-12-31 11:16:03 +01001115 MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001116 }
Paul Bakker78e81962013-12-31 11:16:03 +01001117 MPI_CHK( mpi_shift_r( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001118
1119 for( i = n; i > t ; i-- )
1120 {
1121 if( X.p[i] >= Y.p[t] )
1122 Z.p[i - t - 1] = ~0;
1123 else
1124 {
Manuel Pégourié-Gonnard57291a72014-03-14 09:21:20 +01001125 /*
Manuel Pégourié-Gonnarda9f86e02014-03-14 18:23:26 +01001126 * The version of Clang shipped by Apple with Mavericks around
1127 * 2014-03 can't handle 128-bit division properly. Disable
1128 * 128-bits division for this version. Let's be optimistic and
1129 * assume it'll be fixed in the next minor version (next
1130 * patchlevel is probably a bit too optimistic).
Manuel Pégourié-Gonnard57291a72014-03-14 09:21:20 +01001131 */
Manuel Pégourié-Gonnarda9f86e02014-03-14 18:23:26 +01001132#if defined(POLARSSL_HAVE_UDBL) && \
1133 ! ( defined(__x86_64__) && defined(__APPLE__) && \
1134 defined(__clang_major__) && __clang_major__ == 5 && \
1135 defined(__clang_minor__) && __clang_minor__ == 0 )
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001136 t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001137
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001138 r = (t_udbl) X.p[i] << biL;
1139 r |= (t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001140 r /= Y.p[t];
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001141 if( r > ((t_udbl) 1 << biL) - 1)
1142 r = ((t_udbl) 1 << biL) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001143
Paul Bakkera755ca12011-04-24 09:11:17 +00001144 Z.p[i - t - 1] = (t_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001145#else
1146 /*
1147 * __udiv_qrnnd_c, from gmp/longlong.h
1148 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001149 t_uint q0, q1, r0, r1;
1150 t_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001151
1152 d = Y.p[t];
1153 d0 = ( d << biH ) >> biH;
1154 d1 = ( d >> biH );
1155
1156 q1 = X.p[i] / d1;
1157 r1 = X.p[i] - d1 * q1;
1158 r1 <<= biH;
1159 r1 |= ( X.p[i - 1] >> biH );
1160
1161 m = q1 * d0;
1162 if( r1 < m )
1163 {
1164 q1--, r1 += d;
1165 while( r1 >= d && r1 < m )
1166 q1--, r1 += d;
1167 }
1168 r1 -= m;
1169
1170 q0 = r1 / d1;
1171 r0 = r1 - d1 * q0;
1172 r0 <<= biH;
1173 r0 |= ( X.p[i - 1] << biH ) >> biH;
1174
1175 m = q0 * d0;
1176 if( r0 < m )
1177 {
1178 q0--, r0 += d;
1179 while( r0 >= d && r0 < m )
1180 q0--, r0 += d;
1181 }
1182 r0 -= m;
1183
1184 Z.p[i - t - 1] = ( q1 << biH ) | q0;
1185#endif
1186 }
1187
1188 Z.p[i - t - 1]++;
1189 do
1190 {
1191 Z.p[i - t - 1]--;
1192
1193 MPI_CHK( mpi_lset( &T1, 0 ) );
1194 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1195 T1.p[1] = Y.p[t];
1196 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1197
1198 MPI_CHK( mpi_lset( &T2, 0 ) );
1199 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1200 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1201 T2.p[2] = X.p[i];
1202 }
1203 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1204
1205 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1206 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1207 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1208
1209 if( mpi_cmp_int( &X, 0 ) < 0 )
1210 {
1211 MPI_CHK( mpi_copy( &T1, &Y ) );
1212 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1213 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1214 Z.p[i - t - 1]--;
1215 }
1216 }
1217
1218 if( Q != NULL )
1219 {
Paul Bakker78e81962013-12-31 11:16:03 +01001220 MPI_CHK( mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001221 Q->s = A->s * B->s;
1222 }
1223
1224 if( R != NULL )
1225 {
Paul Bakker78e81962013-12-31 11:16:03 +01001226 MPI_CHK( mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001227 X.s = A->s;
Paul Bakker78e81962013-12-31 11:16:03 +01001228 MPI_CHK( mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001229
Paul Bakker5121ce52009-01-03 21:22:43 +00001230 if( mpi_cmp_int( R, 0 ) == 0 )
1231 R->s = 1;
1232 }
1233
1234cleanup:
1235
Paul Bakker6c591fa2011-05-05 11:49:20 +00001236 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1237 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001238
1239 return( ret );
1240}
1241
1242/*
1243 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001244 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001245int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001246{
1247 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001248 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001249
1250 p[0] = ( b < 0 ) ? -b : b;
1251 _B.s = ( b < 0 ) ? -1 : 1;
1252 _B.n = 1;
1253 _B.p = p;
1254
1255 return( mpi_div_mpi( Q, R, A, &_B ) );
1256}
1257
1258/*
1259 * Modulo: R = A mod B
1260 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001261int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001262{
1263 int ret;
1264
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001265 if( mpi_cmp_int( B, 0 ) < 0 )
1266 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1267
Paul Bakker5121ce52009-01-03 21:22:43 +00001268 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1269
1270 while( mpi_cmp_int( R, 0 ) < 0 )
1271 MPI_CHK( mpi_add_mpi( R, R, B ) );
1272
1273 while( mpi_cmp_mpi( R, B ) >= 0 )
1274 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1275
1276cleanup:
1277
1278 return( ret );
1279}
1280
1281/*
1282 * Modulo: r = A mod b
1283 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001284int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001285{
Paul Bakker23986e52011-04-24 08:57:21 +00001286 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001287 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001288
1289 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001290 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001291
1292 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001293 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001294
1295 /*
1296 * handle trivial cases
1297 */
1298 if( b == 1 )
1299 {
1300 *r = 0;
1301 return( 0 );
1302 }
1303
1304 if( b == 2 )
1305 {
1306 *r = A->p[0] & 1;
1307 return( 0 );
1308 }
1309
1310 /*
1311 * general case
1312 */
Paul Bakker23986e52011-04-24 08:57:21 +00001313 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001314 {
Paul Bakker23986e52011-04-24 08:57:21 +00001315 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001316 y = ( y << biH ) | ( x >> biH );
1317 z = y / b;
1318 y -= z * b;
1319
1320 x <<= biH;
1321 y = ( y << biH ) | ( x >> biH );
1322 z = y / b;
1323 y -= z * b;
1324 }
1325
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001326 /*
1327 * If A is negative, then the current y represents a negative value.
1328 * Flipping it to the positive side.
1329 */
1330 if( A->s < 0 && y != 0 )
1331 y = b - y;
1332
Paul Bakker5121ce52009-01-03 21:22:43 +00001333 *r = y;
1334
1335 return( 0 );
1336}
1337
1338/*
1339 * Fast Montgomery initialization (thanks to Tom St Denis)
1340 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001341static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001342{
Paul Bakkera755ca12011-04-24 09:11:17 +00001343 t_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnard397858b2014-03-11 13:47:05 +01001344 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001345
1346 x = m0;
1347 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001348
Manuel Pégourié-Gonnard397858b2014-03-11 13:47:05 +01001349 for( i = biL; i >= 8; i /= 2 )
1350 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001351
1352 *mm = ~x + 1;
1353}
1354
1355/*
1356 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1357 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001358static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001359{
Paul Bakker23986e52011-04-24 08:57:21 +00001360 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001361 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001362
1363 memset( T->p, 0, T->n * ciL );
1364
1365 d = T->p;
1366 n = N->n;
1367 m = ( B->n < n ) ? B->n : n;
1368
1369 for( i = 0; i < n; i++ )
1370 {
1371 /*
1372 * T = (T + u0*B + u1*N) / 2^biL
1373 */
1374 u0 = A->p[i];
1375 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1376
1377 mpi_mul_hlp( m, B->p, d, u0 );
1378 mpi_mul_hlp( n, N->p, d, u1 );
1379
1380 *d++ = u0; d[n + 1] = 0;
1381 }
1382
1383 memcpy( A->p, d, (n + 1) * ciL );
1384
1385 if( mpi_cmp_abs( A, N ) >= 0 )
1386 mpi_sub_hlp( n, N->p, A->p );
1387 else
1388 /* prevent timing attacks */
1389 mpi_sub_hlp( n, A->p, T->p );
1390}
1391
1392/*
1393 * Montgomery reduction: A = A * R^-1 mod N
1394 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001395static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001396{
Paul Bakkera755ca12011-04-24 09:11:17 +00001397 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001398 mpi U;
1399
Paul Bakker8ddb6452013-02-27 14:56:33 +01001400 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001401 U.p = &z;
1402
1403 mpi_montmul( A, &U, N, mm, T );
1404}
1405
1406/*
1407 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1408 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001409int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001410{
Paul Bakker23986e52011-04-24 08:57:21 +00001411 int ret;
1412 size_t wbits, wsize, one = 1;
1413 size_t i, j, nblimbs;
1414 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001415 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001416 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1417 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001418
1419 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001420 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001421
Paul Bakkerf6198c12012-05-16 08:02:29 +00001422 if( mpi_cmp_int( E, 0 ) < 0 )
1423 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1424
1425 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001426 * Init temps and window size
1427 */
1428 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001429 mpi_init( &RR ); mpi_init( &T );
Manuel Pégourié-Gonnard7fd620b2014-01-18 19:05:23 +01001430 mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001431 memset( W, 0, sizeof( W ) );
1432
1433 i = mpi_msb( E );
1434
1435 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1436 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1437
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001438 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1439 wsize = POLARSSL_MPI_WINDOW_SIZE;
1440
Paul Bakker5121ce52009-01-03 21:22:43 +00001441 j = N->n + 1;
1442 MPI_CHK( mpi_grow( X, j ) );
1443 MPI_CHK( mpi_grow( &W[1], j ) );
1444 MPI_CHK( mpi_grow( &T, j * 2 ) );
1445
1446 /*
Paul Bakker50546922012-05-19 08:40:49 +00001447 * Compensate for negative A (and correct at the end)
1448 */
1449 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001450 if( neg )
1451 {
1452 MPI_CHK( mpi_copy( &Apos, A ) );
1453 Apos.s = 1;
1454 A = &Apos;
1455 }
1456
1457 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001458 * If 1st call, pre-compute R^2 mod N
1459 */
1460 if( _RR == NULL || _RR->p == NULL )
1461 {
1462 MPI_CHK( mpi_lset( &RR, 1 ) );
1463 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1464 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1465
1466 if( _RR != NULL )
1467 memcpy( _RR, &RR, sizeof( mpi ) );
1468 }
1469 else
1470 memcpy( &RR, _RR, sizeof( mpi ) );
1471
1472 /*
1473 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1474 */
1475 if( mpi_cmp_mpi( A, N ) >= 0 )
Paul Bakker1dc45f12014-01-23 20:38:35 +01001476 {
1477 MPI_CHK( mpi_mod_mpi( &W[1], A, N ) );
1478 }
1479 else
1480 MPI_CHK( mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001481
1482 mpi_montmul( &W[1], &RR, N, mm, &T );
1483
1484 /*
1485 * X = R^2 * R^-1 mod N = R mod N
1486 */
1487 MPI_CHK( mpi_copy( X, &RR ) );
1488 mpi_montred( X, N, mm, &T );
1489
1490 if( wsize > 1 )
1491 {
1492 /*
1493 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1494 */
Paul Bakker23986e52011-04-24 08:57:21 +00001495 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001496
1497 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1498 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1499
1500 for( i = 0; i < wsize - 1; i++ )
1501 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakkerc3ec63d2013-10-29 16:18:35 +01001502
Paul Bakker5121ce52009-01-03 21:22:43 +00001503 /*
1504 * W[i] = W[i - 1] * W[1]
1505 */
Paul Bakker23986e52011-04-24 08:57:21 +00001506 for( i = j + 1; i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001507 {
1508 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1509 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1510
1511 mpi_montmul( &W[i], &W[1], N, mm, &T );
1512 }
1513 }
1514
1515 nblimbs = E->n;
1516 bufsize = 0;
1517 nbits = 0;
1518 wbits = 0;
1519 state = 0;
1520
1521 while( 1 )
1522 {
1523 if( bufsize == 0 )
1524 {
Paul Bakkerc3ec63d2013-10-29 16:18:35 +01001525 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001526 break;
1527
Paul Bakkerc3ec63d2013-10-29 16:18:35 +01001528 nblimbs--;
1529
Paul Bakkera755ca12011-04-24 09:11:17 +00001530 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001531 }
1532
1533 bufsize--;
1534
1535 ei = (E->p[nblimbs] >> bufsize) & 1;
1536
1537 /*
1538 * skip leading 0s
1539 */
1540 if( ei == 0 && state == 0 )
1541 continue;
1542
1543 if( ei == 0 && state == 1 )
1544 {
1545 /*
1546 * out of window, square X
1547 */
1548 mpi_montmul( X, X, N, mm, &T );
1549 continue;
1550 }
1551
1552 /*
1553 * add ei to current window
1554 */
1555 state = 2;
1556
1557 nbits++;
1558 wbits |= (ei << (wsize - nbits));
1559
1560 if( nbits == wsize )
1561 {
1562 /*
1563 * X = X^wsize R^-1 mod N
1564 */
1565 for( i = 0; i < wsize; i++ )
1566 mpi_montmul( X, X, N, mm, &T );
1567
1568 /*
1569 * X = X * W[wbits] R^-1 mod N
1570 */
1571 mpi_montmul( X, &W[wbits], N, mm, &T );
1572
1573 state--;
1574 nbits = 0;
1575 wbits = 0;
1576 }
1577 }
1578
1579 /*
1580 * process the remaining bits
1581 */
1582 for( i = 0; i < nbits; i++ )
1583 {
1584 mpi_montmul( X, X, N, mm, &T );
1585
1586 wbits <<= 1;
1587
Paul Bakker23986e52011-04-24 08:57:21 +00001588 if( (wbits & (one << wsize)) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001589 mpi_montmul( X, &W[1], N, mm, &T );
1590 }
1591
1592 /*
1593 * X = A^E * R * R^-1 mod N = A^E mod N
1594 */
1595 mpi_montred( X, N, mm, &T );
1596
Paul Bakkerf6198c12012-05-16 08:02:29 +00001597 if( neg )
1598 {
1599 X->s = -1;
Paul Bakker1dc45f12014-01-23 20:38:35 +01001600 MPI_CHK( mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001601 }
1602
Paul Bakker5121ce52009-01-03 21:22:43 +00001603cleanup:
1604
Paul Bakker23986e52011-04-24 08:57:21 +00001605 for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001606 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001607
Paul Bakkerf6198c12012-05-16 08:02:29 +00001608 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001609
Paul Bakker6995efe2014-03-31 12:08:17 +02001610 if( _RR == NULL || _RR->p == NULL )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001611 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001612
1613 return( ret );
1614}
1615
Paul Bakker5121ce52009-01-03 21:22:43 +00001616/*
1617 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1618 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001619int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001620{
Paul Bakker23986e52011-04-24 08:57:21 +00001621 int ret;
1622 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001623 mpi TG, TA, TB;
1624
Paul Bakker6c591fa2011-05-05 11:49:20 +00001625 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001626
Paul Bakker5121ce52009-01-03 21:22:43 +00001627 MPI_CHK( mpi_copy( &TA, A ) );
1628 MPI_CHK( mpi_copy( &TB, B ) );
1629
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001630 lz = mpi_lsb( &TA );
1631 lzt = mpi_lsb( &TB );
1632
1633 if ( lzt < lz )
1634 lz = lzt;
1635
1636 MPI_CHK( mpi_shift_r( &TA, lz ) );
1637 MPI_CHK( mpi_shift_r( &TB, lz ) );
1638
Paul Bakker5121ce52009-01-03 21:22:43 +00001639 TA.s = TB.s = 1;
1640
1641 while( mpi_cmp_int( &TA, 0 ) != 0 )
1642 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001643 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1644 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001645
1646 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1647 {
1648 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1649 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1650 }
1651 else
1652 {
1653 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1654 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1655 }
1656 }
1657
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001658 MPI_CHK( mpi_shift_l( &TB, lz ) );
1659 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001660
1661cleanup:
1662
Paul Bakker6c591fa2011-05-05 11:49:20 +00001663 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001664
1665 return( ret );
1666}
1667
Paul Bakker358d3252014-04-30 16:11:39 +02001668/*
1669 * Fill X with size bytes of random.
1670 *
1671 * Use a temporary bytes representation to make sure the result is the same
1672 * regardless of the platform endianness (usefull when f_rng is actually
1673 * deterministic, eg for tests).
1674 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001675int mpi_fill_random( mpi *X, size_t size,
1676 int (*f_rng)(void *, unsigned char *, size_t),
1677 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001678{
Paul Bakker23986e52011-04-24 08:57:21 +00001679 int ret;
Paul Bakker358d3252014-04-30 16:11:39 +02001680 unsigned char buf[POLARSSL_MPI_MAX_SIZE];
1681
1682 if( size > POLARSSL_MPI_MAX_SIZE )
1683 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001684
Paul Bakker39dfdac2012-02-12 17:17:27 +00001685 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001686 MPI_CHK( mpi_lset( X, 0 ) );
1687
Paul Bakker358d3252014-04-30 16:11:39 +02001688 MPI_CHK( f_rng( p_rng, buf, size ) );
1689 MPI_CHK( mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001690
1691cleanup:
1692 return( ret );
1693}
1694
Paul Bakker5121ce52009-01-03 21:22:43 +00001695/*
1696 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1697 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001698int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001699{
1700 int ret;
1701 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1702
1703 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001704 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001705
Paul Bakker6c591fa2011-05-05 11:49:20 +00001706 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1707 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1708 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001709
1710 MPI_CHK( mpi_gcd( &G, A, N ) );
1711
1712 if( mpi_cmp_int( &G, 1 ) != 0 )
1713 {
Paul Bakker40e46942009-01-03 21:51:57 +00001714 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001715 goto cleanup;
1716 }
1717
1718 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1719 MPI_CHK( mpi_copy( &TU, &TA ) );
1720 MPI_CHK( mpi_copy( &TB, N ) );
1721 MPI_CHK( mpi_copy( &TV, N ) );
1722
1723 MPI_CHK( mpi_lset( &U1, 1 ) );
1724 MPI_CHK( mpi_lset( &U2, 0 ) );
1725 MPI_CHK( mpi_lset( &V1, 0 ) );
1726 MPI_CHK( mpi_lset( &V2, 1 ) );
1727
1728 do
1729 {
1730 while( ( TU.p[0] & 1 ) == 0 )
1731 {
1732 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1733
1734 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1735 {
1736 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1737 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1738 }
1739
1740 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1741 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1742 }
1743
1744 while( ( TV.p[0] & 1 ) == 0 )
1745 {
1746 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1747
1748 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1749 {
1750 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1751 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1752 }
1753
1754 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1755 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1756 }
1757
1758 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1759 {
1760 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1761 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1762 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1763 }
1764 else
1765 {
1766 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1767 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1768 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1769 }
1770 }
1771 while( mpi_cmp_int( &TU, 0 ) != 0 );
1772
1773 while( mpi_cmp_int( &V1, 0 ) < 0 )
1774 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1775
1776 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1777 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1778
1779 MPI_CHK( mpi_copy( X, &V1 ) );
1780
1781cleanup:
1782
Paul Bakker6c591fa2011-05-05 11:49:20 +00001783 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1784 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1785 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001786
1787 return( ret );
1788}
1789
Paul Bakkerd9374b02012-11-02 11:02:58 +00001790#if defined(POLARSSL_GENPRIME)
1791
Paul Bakker5121ce52009-01-03 21:22:43 +00001792static const int small_prime[] =
1793{
1794 3, 5, 7, 11, 13, 17, 19, 23,
1795 29, 31, 37, 41, 43, 47, 53, 59,
1796 61, 67, 71, 73, 79, 83, 89, 97,
1797 101, 103, 107, 109, 113, 127, 131, 137,
1798 139, 149, 151, 157, 163, 167, 173, 179,
1799 181, 191, 193, 197, 199, 211, 223, 227,
1800 229, 233, 239, 241, 251, 257, 263, 269,
1801 271, 277, 281, 283, 293, 307, 311, 313,
1802 317, 331, 337, 347, 349, 353, 359, 367,
1803 373, 379, 383, 389, 397, 401, 409, 419,
1804 421, 431, 433, 439, 443, 449, 457, 461,
1805 463, 467, 479, 487, 491, 499, 503, 509,
1806 521, 523, 541, 547, 557, 563, 569, 571,
1807 577, 587, 593, 599, 601, 607, 613, 617,
1808 619, 631, 641, 643, 647, 653, 659, 661,
1809 673, 677, 683, 691, 701, 709, 719, 727,
1810 733, 739, 743, 751, 757, 761, 769, 773,
1811 787, 797, 809, 811, 821, 823, 827, 829,
1812 839, 853, 857, 859, 863, 877, 881, 883,
1813 887, 907, 911, 919, 929, 937, 941, 947,
1814 953, 967, 971, 977, 983, 991, 997, -103
1815};
1816
1817/*
1818 * Miller-Rabin primality test (HAC 4.24)
1819 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001820int mpi_is_prime( mpi *X,
1821 int (*f_rng)(void *, unsigned char *, size_t),
1822 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001823{
Paul Bakker23986e52011-04-24 08:57:21 +00001824 int ret, xs;
1825 size_t i, j, n, s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001826 mpi W, R, T, A, RR;
Paul Bakker5121ce52009-01-03 21:22:43 +00001827
Paul Bakker48eab262009-06-25 21:25:49 +00001828 if( mpi_cmp_int( X, 0 ) == 0 ||
1829 mpi_cmp_int( X, 1 ) == 0 )
1830 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1831
1832 if( mpi_cmp_int( X, 2 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001833 return( 0 );
1834
Paul Bakker6c591fa2011-05-05 11:49:20 +00001835 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
1836 mpi_init( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001837
1838 xs = X->s; X->s = 1;
1839
1840 /*
1841 * test trivial factors first
1842 */
1843 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001844 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001845
1846 for( i = 0; small_prime[i] > 0; i++ )
1847 {
Paul Bakkera755ca12011-04-24 09:11:17 +00001848 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001849
1850 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
1851 return( 0 );
1852
1853 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1854
1855 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001856 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001857 }
1858
1859 /*
1860 * W = |X| - 1
1861 * R = W >> lsb( W )
1862 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001863 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001864 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001865 MPI_CHK( mpi_copy( &R, &W ) );
1866 MPI_CHK( mpi_shift_r( &R, s ) );
1867
1868 i = mpi_msb( X );
1869 /*
1870 * HAC, table 4.4
1871 */
1872 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1873 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1874 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1875
1876 for( i = 0; i < n; i++ )
1877 {
1878 /*
1879 * pick a random A, 1 < A < |X| - 1
1880 */
Paul Bakker901c6562012-04-20 13:25:38 +00001881 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001882
Paul Bakkerb94081b2011-01-05 15:53:06 +00001883 if( mpi_cmp_mpi( &A, &W ) >= 0 )
1884 {
1885 j = mpi_msb( &A ) - mpi_msb( &W );
1886 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1887 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001888 A.p[0] |= 3;
1889
1890 /*
1891 * A = A^R mod |X|
1892 */
1893 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1894
1895 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1896 mpi_cmp_int( &A, 1 ) == 0 )
1897 continue;
1898
1899 j = 1;
1900 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1901 {
1902 /*
1903 * A = A * A mod |X|
1904 */
1905 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1906 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1907
1908 if( mpi_cmp_int( &A, 1 ) == 0 )
1909 break;
1910
1911 j++;
1912 }
1913
1914 /*
1915 * not prime if A != |X| - 1 or A == 1
1916 */
1917 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1918 mpi_cmp_int( &A, 1 ) == 0 )
1919 {
Paul Bakker40e46942009-01-03 21:51:57 +00001920 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001921 break;
1922 }
1923 }
1924
1925cleanup:
1926
1927 X->s = xs;
1928
Paul Bakker6c591fa2011-05-05 11:49:20 +00001929 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
1930 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001931
1932 return( ret );
1933}
1934
1935/*
1936 * Prime number generation
1937 */
Paul Bakker23986e52011-04-24 08:57:21 +00001938int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001939 int (*f_rng)(void *, unsigned char *, size_t),
1940 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001941{
Paul Bakker23986e52011-04-24 08:57:21 +00001942 int ret;
1943 size_t k, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001944 mpi Y;
1945
Paul Bakkerfe3256e2011-11-25 12:11:43 +00001946 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00001947 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001948
Paul Bakker6c591fa2011-05-05 11:49:20 +00001949 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001950
1951 n = BITS_TO_LIMBS( nbits );
1952
Paul Bakker901c6562012-04-20 13:25:38 +00001953 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001954
1955 k = mpi_msb( X );
1956 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
1957 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
1958
1959 X->p[0] |= 3;
1960
1961 if( dh_flag == 0 )
1962 {
1963 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
1964 {
Paul Bakker40e46942009-01-03 21:51:57 +00001965 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001966 goto cleanup;
1967
1968 MPI_CHK( mpi_add_int( X, X, 2 ) );
1969 }
1970 }
1971 else
1972 {
1973 MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
1974 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1975
1976 while( 1 )
1977 {
1978 if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
1979 {
1980 if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
1981 break;
1982
Paul Bakker40e46942009-01-03 21:51:57 +00001983 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001984 goto cleanup;
1985 }
1986
Paul Bakker40e46942009-01-03 21:51:57 +00001987 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001988 goto cleanup;
1989
1990 MPI_CHK( mpi_add_int( &Y, X, 1 ) );
1991 MPI_CHK( mpi_add_int( X, X, 2 ) );
1992 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1993 }
1994 }
1995
1996cleanup:
1997
Paul Bakker6c591fa2011-05-05 11:49:20 +00001998 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001999
2000 return( ret );
2001}
2002
2003#endif
2004
Paul Bakker40e46942009-01-03 21:51:57 +00002005#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002006
Paul Bakker23986e52011-04-24 08:57:21 +00002007#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002008
2009static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2010{
2011 { 693, 609, 21 },
2012 { 1764, 868, 28 },
2013 { 768454923, 542167814, 1 }
2014};
2015
Paul Bakker5121ce52009-01-03 21:22:43 +00002016/*
2017 * Checkup routine
2018 */
2019int mpi_self_test( int verbose )
2020{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002021 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002022 mpi A, E, N, X, Y, U, V;
2023
Paul Bakker6c591fa2011-05-05 11:49:20 +00002024 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2025 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002026
2027 MPI_CHK( mpi_read_string( &A, 16,
2028 "EFE021C2645FD1DC586E69184AF4A31E" \
2029 "D5F53E93B5F123FA41680867BA110131" \
2030 "944FE7952E2517337780CB0DB80E61AA" \
2031 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2032
2033 MPI_CHK( mpi_read_string( &E, 16,
2034 "B2E7EFD37075B9F03FF989C7C5051C20" \
2035 "34D2A323810251127E7BF8625A4F49A5" \
2036 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2037 "5B5C25763222FEFCCFC38B832366C29E" ) );
2038
2039 MPI_CHK( mpi_read_string( &N, 16,
2040 "0066A198186C18C10B2F5ED9B522752A" \
2041 "9830B69916E535C8F047518A889A43A5" \
2042 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2043
2044 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2045
2046 MPI_CHK( mpi_read_string( &U, 16,
2047 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2048 "9E857EA95A03512E2BAE7391688D264A" \
2049 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2050 "8001B72E848A38CAE1C65F78E56ABDEF" \
2051 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2052 "ECF677152EF804370C1A305CAF3B5BF1" \
2053 "30879B56C61DE584A0F53A2447A51E" ) );
2054
2055 if( verbose != 0 )
2056 printf( " MPI test #1 (mul_mpi): " );
2057
2058 if( mpi_cmp_mpi( &X, &U ) != 0 )
2059 {
2060 if( verbose != 0 )
2061 printf( "failed\n" );
2062
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002063 ret = 1;
2064 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002065 }
2066
2067 if( verbose != 0 )
2068 printf( "passed\n" );
2069
2070 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2071
2072 MPI_CHK( mpi_read_string( &U, 16,
2073 "256567336059E52CAE22925474705F39A94" ) );
2074
2075 MPI_CHK( mpi_read_string( &V, 16,
2076 "6613F26162223DF488E9CD48CC132C7A" \
2077 "0AC93C701B001B092E4E5B9F73BCD27B" \
2078 "9EE50D0657C77F374E903CDFA4C642" ) );
2079
2080 if( verbose != 0 )
2081 printf( " MPI test #2 (div_mpi): " );
2082
2083 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2084 mpi_cmp_mpi( &Y, &V ) != 0 )
2085 {
2086 if( verbose != 0 )
2087 printf( "failed\n" );
2088
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002089 ret = 1;
2090 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002091 }
2092
2093 if( verbose != 0 )
2094 printf( "passed\n" );
2095
2096 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2097
2098 MPI_CHK( mpi_read_string( &U, 16,
2099 "36E139AEA55215609D2816998ED020BB" \
2100 "BD96C37890F65171D948E9BC7CBAA4D9" \
2101 "325D24D6A3C12710F10A09FA08AB87" ) );
2102
2103 if( verbose != 0 )
2104 printf( " MPI test #3 (exp_mod): " );
2105
2106 if( mpi_cmp_mpi( &X, &U ) != 0 )
2107 {
2108 if( verbose != 0 )
2109 printf( "failed\n" );
2110
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002111 ret = 1;
2112 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002113 }
2114
2115 if( verbose != 0 )
2116 printf( "passed\n" );
2117
Paul Bakker5690efc2011-05-26 13:16:06 +00002118#if defined(POLARSSL_GENPRIME)
Paul Bakker5121ce52009-01-03 21:22:43 +00002119 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2120
2121 MPI_CHK( mpi_read_string( &U, 16,
2122 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2123 "C3DBA76456363A10869622EAC2DD84EC" \
2124 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2125
2126 if( verbose != 0 )
2127 printf( " MPI test #4 (inv_mod): " );
2128
2129 if( mpi_cmp_mpi( &X, &U ) != 0 )
2130 {
2131 if( verbose != 0 )
2132 printf( "failed\n" );
2133
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002134 ret = 1;
2135 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002136 }
2137
2138 if( verbose != 0 )
2139 printf( "passed\n" );
Paul Bakker5690efc2011-05-26 13:16:06 +00002140#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002141
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002142 if( verbose != 0 )
2143 printf( " MPI test #5 (simple gcd): " );
2144
2145 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2146 {
2147 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002148 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002149
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002150 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002151
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002152 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2153 {
2154 if( verbose != 0 )
2155 printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002156
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002157 ret = 1;
2158 goto cleanup;
2159 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002160 }
2161
2162 if( verbose != 0 )
2163 printf( "passed\n" );
2164
Paul Bakker5121ce52009-01-03 21:22:43 +00002165cleanup:
2166
2167 if( ret != 0 && verbose != 0 )
2168 printf( "Unexpected error, return code = %08X\n", ret );
2169
Paul Bakker6c591fa2011-05-05 11:49:20 +00002170 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2171 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002172
2173 if( verbose != 0 )
2174 printf( "\n" );
2175
2176 return( ret );
2177}
2178
2179#endif
2180
2181#endif