blob: cf6ff5a420036694940a213226ad798eec409580 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard0edee5e2015-01-26 15:29:40 +00004 * Copyright (C) 2006-2010, ARM Limited, All Rights Reserved
Paul Bakkerb96f1542010-07-18 20:36:00 +00005 *
Manuel Pégourié-Gonnard0edee5e2015-01-26 15:29:40 +00006 * This file is part of mbed TLS (https://www.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
48/*
49 * Convert between bits/chars and number of limbs
50 */
51#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL)
52#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
53
54/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000055 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000056 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000057void mpi_init( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000058{
Paul Bakker6c591fa2011-05-05 11:49:20 +000059 if( X == NULL )
60 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000061
Paul Bakker6c591fa2011-05-05 11:49:20 +000062 X->s = 1;
63 X->n = 0;
64 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000065}
66
67/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000068 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000069 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000070void mpi_free( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000071{
Paul Bakker6c591fa2011-05-05 11:49:20 +000072 if( X == NULL )
73 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000074
Paul Bakker6c591fa2011-05-05 11:49:20 +000075 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +000076 {
Paul Bakker312da332014-06-13 17:20:13 +020077 polarssl_zeroize( X->p, X->n * ciL );
Paul Bakker6c591fa2011-05-05 11:49:20 +000078 free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +000079 }
80
Paul Bakker6c591fa2011-05-05 11:49:20 +000081 X->s = 1;
82 X->n = 0;
83 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000084}
85
86/*
87 * Enlarge to the specified number of limbs
88 */
Paul Bakker23986e52011-04-24 08:57:21 +000089int mpi_grow( mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +000090{
Paul Bakkera755ca12011-04-24 09:11:17 +000091 t_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +000092
Paul Bakkerf9688572011-05-05 10:00:45 +000093 if( nblimbs > POLARSSL_MPI_MAX_LIMBS )
Paul Bakker69e095c2011-12-10 21:55:01 +000094 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +000095
Paul Bakker5121ce52009-01-03 21:22:43 +000096 if( X->n < nblimbs )
97 {
Paul Bakkera755ca12011-04-24 09:11:17 +000098 if( ( p = (t_uint *) malloc( nblimbs * ciL ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +000099 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000100
101 memset( p, 0, nblimbs * ciL );
102
103 if( X->p != NULL )
104 {
105 memcpy( p, X->p, X->n * ciL );
Paul Bakker312da332014-06-13 17:20:13 +0200106 polarssl_zeroize( X->p, X->n * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000107 free( X->p );
108 }
109
110 X->n = nblimbs;
111 X->p = p;
112 }
113
114 return( 0 );
115}
116
117/*
118 * Copy the contents of Y into X
119 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000120int mpi_copy( mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000121{
Paul Bakker23986e52011-04-24 08:57:21 +0000122 int ret;
123 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000124
125 if( X == Y )
126 return( 0 );
127
128 for( i = Y->n - 1; i > 0; i-- )
129 if( Y->p[i] != 0 )
130 break;
131 i++;
132
133 X->s = Y->s;
134
135 MPI_CHK( mpi_grow( X, i ) );
136
137 memset( X->p, 0, X->n * ciL );
138 memcpy( X->p, Y->p, i * ciL );
139
140cleanup:
141
142 return( ret );
143}
144
145/*
146 * Swap the contents of X and Y
147 */
148void mpi_swap( mpi *X, mpi *Y )
149{
150 mpi T;
151
152 memcpy( &T, X, sizeof( mpi ) );
153 memcpy( X, Y, sizeof( mpi ) );
154 memcpy( Y, &T, sizeof( mpi ) );
155}
156
157/*
158 * Set value from integer
159 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000160int mpi_lset( mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000161{
162 int ret;
163
164 MPI_CHK( mpi_grow( X, 1 ) );
165 memset( X->p, 0, X->n * ciL );
166
167 X->p[0] = ( z < 0 ) ? -z : z;
168 X->s = ( z < 0 ) ? -1 : 1;
169
170cleanup:
171
172 return( ret );
173}
174
175/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000176 * Get a specific bit
177 */
Paul Bakker6b906e52012-05-08 12:01:43 +0000178int mpi_get_bit( const mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000179{
180 if( X->n * biL <= pos )
181 return( 0 );
182
183 return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
184}
185
186/*
187 * Set a bit to a specific value of 0 or 1
188 */
189int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
190{
191 int ret = 0;
192 size_t off = pos / biL;
193 size_t idx = pos % biL;
194
195 if( val != 0 && val != 1 )
196 return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
197
198 if( X->n * biL <= pos )
199 {
200 if( val == 0 )
201 return ( 0 );
202
203 MPI_CHK( mpi_grow( X, off + 1 ) );
204 }
205
206 X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
207
208cleanup:
209
210 return( ret );
211}
212
213/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000214 * Return the number of least significant bits
215 */
Paul Bakker23986e52011-04-24 08:57:21 +0000216size_t mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000217{
Paul Bakker23986e52011-04-24 08:57:21 +0000218 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000219
220 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000221 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000222 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
223 return( count );
224
225 return( 0 );
226}
227
228/*
229 * Return the number of most significant bits
230 */
Paul Bakker23986e52011-04-24 08:57:21 +0000231size_t mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000232{
Paul Bakker23986e52011-04-24 08:57:21 +0000233 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000234
235 for( i = X->n - 1; i > 0; i-- )
236 if( X->p[i] != 0 )
237 break;
238
Paul Bakker23986e52011-04-24 08:57:21 +0000239 for( j = biL; j > 0; j-- )
240 if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000241 break;
242
Paul Bakker23986e52011-04-24 08:57:21 +0000243 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000244}
245
246/*
247 * Return the total size in bytes
248 */
Paul Bakker23986e52011-04-24 08:57:21 +0000249size_t mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000250{
251 return( ( mpi_msb( X ) + 7 ) >> 3 );
252}
253
254/*
255 * Convert an ASCII character to digit value
256 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000257static int mpi_get_digit( t_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000258{
259 *d = 255;
260
261 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
262 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
263 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
264
Paul Bakkera755ca12011-04-24 09:11:17 +0000265 if( *d >= (t_uint) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000266 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000267
268 return( 0 );
269}
270
271/*
272 * Import from an ASCII string
273 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000274int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000275{
Paul Bakker23986e52011-04-24 08:57:21 +0000276 int ret;
277 size_t i, j, slen, n;
Paul Bakkera755ca12011-04-24 09:11:17 +0000278 t_uint d;
Paul Bakker5121ce52009-01-03 21:22:43 +0000279 mpi T;
280
281 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000282 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000283
Paul Bakker6c591fa2011-05-05 11:49:20 +0000284 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000285
Paul Bakkerff60ee62010-03-16 21:09:09 +0000286 slen = strlen( s );
287
Paul Bakker5121ce52009-01-03 21:22:43 +0000288 if( radix == 16 )
289 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000290 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000291
292 MPI_CHK( mpi_grow( X, n ) );
293 MPI_CHK( mpi_lset( X, 0 ) );
294
Paul Bakker23986e52011-04-24 08:57:21 +0000295 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000296 {
Paul Bakker23986e52011-04-24 08:57:21 +0000297 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000298 {
299 X->s = -1;
300 break;
301 }
302
Paul Bakker23986e52011-04-24 08:57:21 +0000303 MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000304 X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
305 }
306 }
307 else
308 {
309 MPI_CHK( mpi_lset( X, 0 ) );
310
Paul Bakkerff60ee62010-03-16 21:09:09 +0000311 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000312 {
313 if( i == 0 && s[i] == '-' )
314 {
315 X->s = -1;
316 continue;
317 }
318
319 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
320 MPI_CHK( mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000321
322 if( X->s == 1 )
323 {
324 MPI_CHK( mpi_add_int( X, &T, d ) );
325 }
326 else
327 {
328 MPI_CHK( mpi_sub_int( X, &T, d ) );
329 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000330 }
331 }
332
333cleanup:
334
Paul Bakker6c591fa2011-05-05 11:49:20 +0000335 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000336
337 return( ret );
338}
339
340/*
341 * Helper to write the digits high-order first
342 */
343static int mpi_write_hlp( mpi *X, int radix, char **p )
344{
345 int ret;
Paul Bakkera755ca12011-04-24 09:11:17 +0000346 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000347
348 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000349 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000350
351 MPI_CHK( mpi_mod_int( &r, X, radix ) );
352 MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
353
354 if( mpi_cmp_int( X, 0 ) != 0 )
355 MPI_CHK( mpi_write_hlp( X, radix, p ) );
356
357 if( r < 10 )
358 *(*p)++ = (char)( r + 0x30 );
359 else
360 *(*p)++ = (char)( r + 0x37 );
361
362cleanup:
363
364 return( ret );
365}
366
367/*
368 * Export into an ASCII string
369 */
Paul Bakker23986e52011-04-24 08:57:21 +0000370int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000371{
Paul Bakker23986e52011-04-24 08:57:21 +0000372 int ret = 0;
373 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000374 char *p;
375 mpi T;
376
377 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000378 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000379
380 n = mpi_msb( X );
381 if( radix >= 4 ) n >>= 1;
382 if( radix >= 16 ) n >>= 1;
383 n += 3;
384
385 if( *slen < n )
386 {
387 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000388 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000389 }
390
391 p = s;
Paul Bakker6c591fa2011-05-05 11:49:20 +0000392 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000393
394 if( X->s == -1 )
395 *p++ = '-';
396
397 if( radix == 16 )
398 {
Paul Bakker23986e52011-04-24 08:57:21 +0000399 int c;
400 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000401
Paul Bakker23986e52011-04-24 08:57:21 +0000402 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000403 {
Paul Bakker23986e52011-04-24 08:57:21 +0000404 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000405 {
Paul Bakker23986e52011-04-24 08:57:21 +0000406 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000407
Paul Bakker23986e52011-04-24 08:57:21 +0000408 if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000409 continue;
410
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000411 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000412 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000413 k = 1;
414 }
415 }
416 }
417 else
418 {
419 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000420
421 if( T.s == -1 )
422 T.s = 1;
423
Paul Bakker5121ce52009-01-03 21:22:43 +0000424 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
425 }
426
427 *p++ = '\0';
428 *slen = p - s;
429
430cleanup:
431
Paul Bakker6c591fa2011-05-05 11:49:20 +0000432 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000433
434 return( ret );
435}
436
Paul Bakker335db3f2011-04-25 15:28:35 +0000437#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000438/*
439 * Read X from an opened file
440 */
441int mpi_read_file( mpi *X, int radix, FILE *fin )
442{
Paul Bakkera755ca12011-04-24 09:11:17 +0000443 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000444 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000445 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000446 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000447 * Buffer should have space for (short) label and decimal formatted MPI,
448 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000449 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000450 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000451
452 memset( s, 0, sizeof( s ) );
453 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000454 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000455
456 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000457 if( slen == sizeof( s ) - 2 )
458 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
459
Paul Bakker5121ce52009-01-03 21:22:43 +0000460 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
461 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
462
463 p = s + slen;
464 while( --p >= s )
465 if( mpi_get_digit( &d, radix, *p ) != 0 )
466 break;
467
468 return( mpi_read_string( X, radix, p + 1 ) );
469}
470
471/*
472 * Write X into an opened file (or stdout if fout == NULL)
473 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000474int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000475{
Paul Bakker23986e52011-04-24 08:57:21 +0000476 int ret;
477 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000478 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000479 * Buffer should have space for (short) label and decimal formatted MPI,
480 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000481 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000482 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
484 n = sizeof( s );
485 memset( s, 0, n );
486 n -= 2;
487
Paul Bakker23986e52011-04-24 08:57:21 +0000488 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000489
490 if( p == NULL ) p = "";
491
492 plen = strlen( p );
493 slen = strlen( s );
494 s[slen++] = '\r';
495 s[slen++] = '\n';
496
497 if( fout != NULL )
498 {
499 if( fwrite( p, 1, plen, fout ) != plen ||
500 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000501 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000502 }
503 else
504 printf( "%s%s", p, s );
505
506cleanup:
507
508 return( ret );
509}
Paul Bakker335db3f2011-04-25 15:28:35 +0000510#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000511
512/*
513 * Import X from unsigned binary data, big endian
514 */
Paul Bakker23986e52011-04-24 08:57:21 +0000515int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000516{
Paul Bakker23986e52011-04-24 08:57:21 +0000517 int ret;
518 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000519
520 for( n = 0; n < buflen; n++ )
521 if( buf[n] != 0 )
522 break;
523
524 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
525 MPI_CHK( mpi_lset( X, 0 ) );
526
Paul Bakker23986e52011-04-24 08:57:21 +0000527 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000528 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000529
530cleanup:
531
532 return( ret );
533}
534
535/*
536 * Export X into unsigned binary data, big endian
537 */
Paul Bakker23986e52011-04-24 08:57:21 +0000538int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000539{
Paul Bakker23986e52011-04-24 08:57:21 +0000540 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000541
542 n = mpi_size( X );
543
544 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000545 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000546
547 memset( buf, 0, buflen );
548
549 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
550 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
551
552 return( 0 );
553}
554
555/*
556 * Left-shift: X <<= count
557 */
Paul Bakker23986e52011-04-24 08:57:21 +0000558int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000559{
Paul Bakker23986e52011-04-24 08:57:21 +0000560 int ret;
561 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000562 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000563
564 v0 = count / (biL );
565 t1 = count & (biL - 1);
566
567 i = mpi_msb( X ) + count;
568
Paul Bakkerf9688572011-05-05 10:00:45 +0000569 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000570 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
571
572 ret = 0;
573
574 /*
575 * shift by count / limb_size
576 */
577 if( v0 > 0 )
578 {
Paul Bakker23986e52011-04-24 08:57:21 +0000579 for( i = X->n; i > v0; i-- )
580 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000581
Paul Bakker23986e52011-04-24 08:57:21 +0000582 for( ; i > 0; i-- )
583 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000584 }
585
586 /*
587 * shift by count % limb_size
588 */
589 if( t1 > 0 )
590 {
591 for( i = v0; i < X->n; i++ )
592 {
593 r1 = X->p[i] >> (biL - t1);
594 X->p[i] <<= t1;
595 X->p[i] |= r0;
596 r0 = r1;
597 }
598 }
599
600cleanup:
601
602 return( ret );
603}
604
605/*
606 * Right-shift: X >>= count
607 */
Paul Bakker23986e52011-04-24 08:57:21 +0000608int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000609{
Paul Bakker23986e52011-04-24 08:57:21 +0000610 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000611 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000612
613 v0 = count / biL;
614 v1 = count & (biL - 1);
615
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100616 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
617 return mpi_lset( X, 0 );
618
Paul Bakker5121ce52009-01-03 21:22:43 +0000619 /*
620 * shift by count / limb_size
621 */
622 if( v0 > 0 )
623 {
624 for( i = 0; i < X->n - v0; i++ )
625 X->p[i] = X->p[i + v0];
626
627 for( ; i < X->n; i++ )
628 X->p[i] = 0;
629 }
630
631 /*
632 * shift by count % limb_size
633 */
634 if( v1 > 0 )
635 {
Paul Bakker23986e52011-04-24 08:57:21 +0000636 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000637 {
Paul Bakker23986e52011-04-24 08:57:21 +0000638 r1 = X->p[i - 1] << (biL - v1);
639 X->p[i - 1] >>= v1;
640 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000641 r0 = r1;
642 }
643 }
644
645 return( 0 );
646}
647
648/*
649 * Compare unsigned values
650 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000651int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000652{
Paul Bakker23986e52011-04-24 08:57:21 +0000653 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000654
Paul Bakker23986e52011-04-24 08:57:21 +0000655 for( i = X->n; i > 0; i-- )
656 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000657 break;
658
Paul Bakker23986e52011-04-24 08:57:21 +0000659 for( j = Y->n; j > 0; j-- )
660 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000661 break;
662
Paul Bakker23986e52011-04-24 08:57:21 +0000663 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000664 return( 0 );
665
666 if( i > j ) return( 1 );
667 if( j > i ) return( -1 );
668
Paul Bakker23986e52011-04-24 08:57:21 +0000669 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000670 {
Paul Bakker23986e52011-04-24 08:57:21 +0000671 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
672 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000673 }
674
675 return( 0 );
676}
677
678/*
679 * Compare signed values
680 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000681int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000682{
Paul Bakker23986e52011-04-24 08:57:21 +0000683 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000684
Paul Bakker23986e52011-04-24 08:57:21 +0000685 for( i = X->n; i > 0; i-- )
686 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000687 break;
688
Paul Bakker23986e52011-04-24 08:57:21 +0000689 for( j = Y->n; j > 0; j-- )
690 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000691 break;
692
Paul Bakker23986e52011-04-24 08:57:21 +0000693 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000694 return( 0 );
695
696 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000697 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
699 if( X->s > 0 && Y->s < 0 ) return( 1 );
700 if( Y->s > 0 && X->s < 0 ) return( -1 );
701
Paul Bakker23986e52011-04-24 08:57:21 +0000702 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000703 {
Paul Bakker23986e52011-04-24 08:57:21 +0000704 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
705 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000706 }
707
708 return( 0 );
709}
710
711/*
712 * Compare signed values
713 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000714int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000715{
716 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000717 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000718
719 *p = ( z < 0 ) ? -z : z;
720 Y.s = ( z < 0 ) ? -1 : 1;
721 Y.n = 1;
722 Y.p = p;
723
724 return( mpi_cmp_mpi( X, &Y ) );
725}
726
727/*
728 * Unsigned addition: X = |A| + |B| (HAC 14.7)
729 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000730int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000731{
Paul Bakker23986e52011-04-24 08:57:21 +0000732 int ret;
733 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000734 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000735
736 if( X == B )
737 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000738 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000739 }
740
741 if( X != A )
742 MPI_CHK( mpi_copy( X, A ) );
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000743
744 /*
745 * X should always be positive as a result of unsigned additions.
746 */
747 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000748
Paul Bakker23986e52011-04-24 08:57:21 +0000749 for( j = B->n; j > 0; j-- )
750 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000751 break;
752
Paul Bakker23986e52011-04-24 08:57:21 +0000753 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000754
755 o = B->p; p = X->p; c = 0;
756
Paul Bakker23986e52011-04-24 08:57:21 +0000757 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000758 {
759 *p += c; c = ( *p < c );
760 *p += *o; c += ( *p < *o );
761 }
762
763 while( c != 0 )
764 {
765 if( i >= X->n )
766 {
767 MPI_CHK( mpi_grow( X, i + 1 ) );
768 p = X->p + i;
769 }
770
Paul Bakker2d319fd2012-09-16 21:34:26 +0000771 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000772 }
773
774cleanup:
775
776 return( ret );
777}
778
779/*
780 * Helper for mpi substraction
781 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000782static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000783{
Paul Bakker23986e52011-04-24 08:57:21 +0000784 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000785 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000786
787 for( i = c = 0; i < n; i++, s++, d++ )
788 {
789 z = ( *d < c ); *d -= c;
790 c = ( *d < *s ) + z; *d -= *s;
791 }
792
793 while( c != 0 )
794 {
795 z = ( *d < c ); *d -= c;
796 c = z; i++; d++;
797 }
798}
799
800/*
801 * Unsigned substraction: X = |A| - |B| (HAC 14.9)
802 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000803int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000804{
805 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000806 int ret;
807 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000808
809 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000810 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000811
Paul Bakker6c591fa2011-05-05 11:49:20 +0000812 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000813
814 if( X == B )
815 {
816 MPI_CHK( mpi_copy( &TB, B ) );
817 B = &TB;
818 }
819
820 if( X != A )
821 MPI_CHK( mpi_copy( X, A ) );
822
Paul Bakker1ef7a532009-06-20 10:50:55 +0000823 /*
824 * X should always be positive as a result of unsigned substractions.
825 */
826 X->s = 1;
827
Paul Bakker5121ce52009-01-03 21:22:43 +0000828 ret = 0;
829
Paul Bakker23986e52011-04-24 08:57:21 +0000830 for( n = B->n; n > 0; n-- )
831 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000832 break;
833
Paul Bakker23986e52011-04-24 08:57:21 +0000834 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000835
836cleanup:
837
Paul Bakker6c591fa2011-05-05 11:49:20 +0000838 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000839
840 return( ret );
841}
842
843/*
844 * Signed addition: X = A + B
845 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000846int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000847{
848 int ret, s = A->s;
849
850 if( A->s * B->s < 0 )
851 {
852 if( mpi_cmp_abs( A, B ) >= 0 )
853 {
854 MPI_CHK( mpi_sub_abs( X, A, B ) );
855 X->s = s;
856 }
857 else
858 {
859 MPI_CHK( mpi_sub_abs( X, B, A ) );
860 X->s = -s;
861 }
862 }
863 else
864 {
865 MPI_CHK( mpi_add_abs( X, A, B ) );
866 X->s = s;
867 }
868
869cleanup:
870
871 return( ret );
872}
873
874/*
875 * Signed substraction: X = A - B
876 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000877int mpi_sub_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 addition: X = A + b
907 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000908int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000909{
910 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000911 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000912
913 p[0] = ( b < 0 ) ? -b : b;
914 _B.s = ( b < 0 ) ? -1 : 1;
915 _B.n = 1;
916 _B.p = p;
917
918 return( mpi_add_mpi( X, A, &_B ) );
919}
920
921/*
922 * Signed substraction: X = A - b
923 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000924int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000925{
926 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000927 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000928
929 p[0] = ( b < 0 ) ? -b : b;
930 _B.s = ( b < 0 ) ? -1 : 1;
931 _B.n = 1;
932 _B.p = p;
933
934 return( mpi_sub_mpi( X, A, &_B ) );
935}
936
937/*
938 * Helper for mpi multiplication
Paul Bakker52b845b2013-06-14 11:36:56 +0200939 */
940static
941#if defined(__APPLE__) && defined(__arm__)
942/*
943 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
944 * appears to need this to prevent bad ARM code generation at -O3.
945 */
946__attribute__ ((noinline))
947#endif
948void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000949{
Paul Bakkera755ca12011-04-24 09:11:17 +0000950 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000951
952#if defined(MULADDC_HUIT)
953 for( ; i >= 8; i -= 8 )
954 {
955 MULADDC_INIT
956 MULADDC_HUIT
957 MULADDC_STOP
958 }
959
960 for( ; i > 0; i-- )
961 {
962 MULADDC_INIT
963 MULADDC_CORE
964 MULADDC_STOP
965 }
966#else
967 for( ; i >= 16; i -= 16 )
968 {
969 MULADDC_INIT
970 MULADDC_CORE MULADDC_CORE
971 MULADDC_CORE MULADDC_CORE
972 MULADDC_CORE MULADDC_CORE
973 MULADDC_CORE MULADDC_CORE
974
975 MULADDC_CORE MULADDC_CORE
976 MULADDC_CORE MULADDC_CORE
977 MULADDC_CORE MULADDC_CORE
978 MULADDC_CORE MULADDC_CORE
979 MULADDC_STOP
980 }
981
982 for( ; i >= 8; i -= 8 )
983 {
984 MULADDC_INIT
985 MULADDC_CORE MULADDC_CORE
986 MULADDC_CORE MULADDC_CORE
987
988 MULADDC_CORE MULADDC_CORE
989 MULADDC_CORE MULADDC_CORE
990 MULADDC_STOP
991 }
992
993 for( ; i > 0; i-- )
994 {
995 MULADDC_INIT
996 MULADDC_CORE
997 MULADDC_STOP
998 }
999#endif
1000
1001 t++;
1002
1003 do {
1004 *d += c; c = ( *d < c ); d++;
1005 }
1006 while( c != 0 );
1007}
1008
1009/*
1010 * Baseline multiplication: X = A * B (HAC 14.12)
1011 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001012int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001013{
Paul Bakker23986e52011-04-24 08:57:21 +00001014 int ret;
1015 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001016 mpi TA, TB;
1017
Paul Bakker6c591fa2011-05-05 11:49:20 +00001018 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001019
1020 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1021 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1022
Paul Bakker23986e52011-04-24 08:57:21 +00001023 for( i = A->n; i > 0; i-- )
1024 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001025 break;
1026
Paul Bakker23986e52011-04-24 08:57:21 +00001027 for( j = B->n; j > 0; j-- )
1028 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001029 break;
1030
Paul Bakker23986e52011-04-24 08:57:21 +00001031 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001032 MPI_CHK( mpi_lset( X, 0 ) );
1033
Paul Bakker23986e52011-04-24 08:57:21 +00001034 for( i++; j > 0; j-- )
1035 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001036
1037 X->s = A->s * B->s;
1038
1039cleanup:
1040
Paul Bakker6c591fa2011-05-05 11:49:20 +00001041 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001042
1043 return( ret );
1044}
1045
1046/*
1047 * Baseline multiplication: X = A * b
1048 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001049int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001050{
1051 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001052 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001053
1054 _B.s = 1;
1055 _B.n = 1;
1056 _B.p = p;
1057 p[0] = b;
1058
1059 return( mpi_mul_mpi( X, A, &_B ) );
1060}
1061
1062/*
1063 * Division by mpi: A = Q * B + R (HAC 14.20)
1064 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001065int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001066{
Paul Bakker23986e52011-04-24 08:57:21 +00001067 int ret;
1068 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001069 mpi X, Y, Z, T1, T2;
1070
1071 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001072 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001073
Paul Bakker6c591fa2011-05-05 11:49:20 +00001074 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1075 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001076
1077 if( mpi_cmp_abs( A, B ) < 0 )
1078 {
1079 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1080 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1081 return( 0 );
1082 }
1083
1084 MPI_CHK( mpi_copy( &X, A ) );
1085 MPI_CHK( mpi_copy( &Y, B ) );
1086 X.s = Y.s = 1;
1087
1088 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1089 MPI_CHK( mpi_lset( &Z, 0 ) );
1090 MPI_CHK( mpi_grow( &T1, 2 ) );
1091 MPI_CHK( mpi_grow( &T2, 3 ) );
1092
1093 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001094 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001095 {
1096 k = biL - 1 - k;
1097 MPI_CHK( mpi_shift_l( &X, k ) );
1098 MPI_CHK( mpi_shift_l( &Y, k ) );
1099 }
1100 else k = 0;
1101
1102 n = X.n - 1;
1103 t = Y.n - 1;
Paul Bakkerc110d022012-10-19 12:15:08 +00001104 MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001105
1106 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1107 {
1108 Z.p[n - t]++;
Paul Bakker78e81962013-12-31 11:16:03 +01001109 MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001110 }
Paul Bakker78e81962013-12-31 11:16:03 +01001111 MPI_CHK( mpi_shift_r( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001112
1113 for( i = n; i > t ; i-- )
1114 {
1115 if( X.p[i] >= Y.p[t] )
1116 Z.p[i - t - 1] = ~0;
1117 else
1118 {
Manuel Pégourié-Gonnard57291a72014-03-14 09:21:20 +01001119 /*
Manuel Pégourié-Gonnarda9f86e02014-03-14 18:23:26 +01001120 * The version of Clang shipped by Apple with Mavericks around
1121 * 2014-03 can't handle 128-bit division properly. Disable
1122 * 128-bits division for this version. Let's be optimistic and
1123 * assume it'll be fixed in the next minor version (next
1124 * patchlevel is probably a bit too optimistic).
Manuel Pégourié-Gonnard57291a72014-03-14 09:21:20 +01001125 */
Manuel Pégourié-Gonnarda9f86e02014-03-14 18:23:26 +01001126#if defined(POLARSSL_HAVE_UDBL) && \
1127 ! ( defined(__x86_64__) && defined(__APPLE__) && \
1128 defined(__clang_major__) && __clang_major__ == 5 && \
1129 defined(__clang_minor__) && __clang_minor__ == 0 )
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001130 t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001131
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001132 r = (t_udbl) X.p[i] << biL;
1133 r |= (t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001134 r /= Y.p[t];
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001135 if( r > ((t_udbl) 1 << biL) - 1)
1136 r = ((t_udbl) 1 << biL) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001137
Paul Bakkera755ca12011-04-24 09:11:17 +00001138 Z.p[i - t - 1] = (t_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001139#else
1140 /*
1141 * __udiv_qrnnd_c, from gmp/longlong.h
1142 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001143 t_uint q0, q1, r0, r1;
1144 t_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001145
1146 d = Y.p[t];
1147 d0 = ( d << biH ) >> biH;
1148 d1 = ( d >> biH );
1149
1150 q1 = X.p[i] / d1;
1151 r1 = X.p[i] - d1 * q1;
1152 r1 <<= biH;
1153 r1 |= ( X.p[i - 1] >> biH );
1154
1155 m = q1 * d0;
1156 if( r1 < m )
1157 {
1158 q1--, r1 += d;
1159 while( r1 >= d && r1 < m )
1160 q1--, r1 += d;
1161 }
1162 r1 -= m;
1163
1164 q0 = r1 / d1;
1165 r0 = r1 - d1 * q0;
1166 r0 <<= biH;
1167 r0 |= ( X.p[i - 1] << biH ) >> biH;
1168
1169 m = q0 * d0;
1170 if( r0 < m )
1171 {
1172 q0--, r0 += d;
1173 while( r0 >= d && r0 < m )
1174 q0--, r0 += d;
1175 }
1176 r0 -= m;
1177
1178 Z.p[i - t - 1] = ( q1 << biH ) | q0;
1179#endif
1180 }
1181
1182 Z.p[i - t - 1]++;
1183 do
1184 {
1185 Z.p[i - t - 1]--;
1186
1187 MPI_CHK( mpi_lset( &T1, 0 ) );
1188 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1189 T1.p[1] = Y.p[t];
1190 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1191
1192 MPI_CHK( mpi_lset( &T2, 0 ) );
1193 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1194 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1195 T2.p[2] = X.p[i];
1196 }
1197 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1198
1199 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1200 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1201 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1202
1203 if( mpi_cmp_int( &X, 0 ) < 0 )
1204 {
1205 MPI_CHK( mpi_copy( &T1, &Y ) );
1206 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1207 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1208 Z.p[i - t - 1]--;
1209 }
1210 }
1211
1212 if( Q != NULL )
1213 {
Paul Bakker78e81962013-12-31 11:16:03 +01001214 MPI_CHK( mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001215 Q->s = A->s * B->s;
1216 }
1217
1218 if( R != NULL )
1219 {
Paul Bakker78e81962013-12-31 11:16:03 +01001220 MPI_CHK( mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001221 X.s = A->s;
Paul Bakker78e81962013-12-31 11:16:03 +01001222 MPI_CHK( mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001223
Paul Bakker5121ce52009-01-03 21:22:43 +00001224 if( mpi_cmp_int( R, 0 ) == 0 )
1225 R->s = 1;
1226 }
1227
1228cleanup:
1229
Paul Bakker6c591fa2011-05-05 11:49:20 +00001230 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1231 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001232
1233 return( ret );
1234}
1235
1236/*
1237 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001238 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001239int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001240{
1241 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001242 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001243
1244 p[0] = ( b < 0 ) ? -b : b;
1245 _B.s = ( b < 0 ) ? -1 : 1;
1246 _B.n = 1;
1247 _B.p = p;
1248
1249 return( mpi_div_mpi( Q, R, A, &_B ) );
1250}
1251
1252/*
1253 * Modulo: R = A mod B
1254 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001255int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001256{
1257 int ret;
1258
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001259 if( mpi_cmp_int( B, 0 ) < 0 )
1260 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1261
Paul Bakker5121ce52009-01-03 21:22:43 +00001262 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1263
1264 while( mpi_cmp_int( R, 0 ) < 0 )
1265 MPI_CHK( mpi_add_mpi( R, R, B ) );
1266
1267 while( mpi_cmp_mpi( R, B ) >= 0 )
1268 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1269
1270cleanup:
1271
1272 return( ret );
1273}
1274
1275/*
1276 * Modulo: r = A mod b
1277 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001278int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001279{
Paul Bakker23986e52011-04-24 08:57:21 +00001280 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001281 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001282
1283 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001284 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001285
1286 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001287 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001288
1289 /*
1290 * handle trivial cases
1291 */
1292 if( b == 1 )
1293 {
1294 *r = 0;
1295 return( 0 );
1296 }
1297
1298 if( b == 2 )
1299 {
1300 *r = A->p[0] & 1;
1301 return( 0 );
1302 }
1303
1304 /*
1305 * general case
1306 */
Paul Bakker23986e52011-04-24 08:57:21 +00001307 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001308 {
Paul Bakker23986e52011-04-24 08:57:21 +00001309 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001310 y = ( y << biH ) | ( x >> biH );
1311 z = y / b;
1312 y -= z * b;
1313
1314 x <<= biH;
1315 y = ( y << biH ) | ( x >> biH );
1316 z = y / b;
1317 y -= z * b;
1318 }
1319
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001320 /*
1321 * If A is negative, then the current y represents a negative value.
1322 * Flipping it to the positive side.
1323 */
1324 if( A->s < 0 && y != 0 )
1325 y = b - y;
1326
Paul Bakker5121ce52009-01-03 21:22:43 +00001327 *r = y;
1328
1329 return( 0 );
1330}
1331
1332/*
1333 * Fast Montgomery initialization (thanks to Tom St Denis)
1334 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001335static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001336{
Paul Bakkera755ca12011-04-24 09:11:17 +00001337 t_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnard397858b2014-03-11 13:47:05 +01001338 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001339
1340 x = m0;
1341 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001342
Manuel Pégourié-Gonnard397858b2014-03-11 13:47:05 +01001343 for( i = biL; i >= 8; i /= 2 )
1344 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001345
1346 *mm = ~x + 1;
1347}
1348
1349/*
1350 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1351 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001352static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001353{
Paul Bakker23986e52011-04-24 08:57:21 +00001354 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001355 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001356
1357 memset( T->p, 0, T->n * ciL );
1358
1359 d = T->p;
1360 n = N->n;
1361 m = ( B->n < n ) ? B->n : n;
1362
1363 for( i = 0; i < n; i++ )
1364 {
1365 /*
1366 * T = (T + u0*B + u1*N) / 2^biL
1367 */
1368 u0 = A->p[i];
1369 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1370
1371 mpi_mul_hlp( m, B->p, d, u0 );
1372 mpi_mul_hlp( n, N->p, d, u1 );
1373
1374 *d++ = u0; d[n + 1] = 0;
1375 }
1376
1377 memcpy( A->p, d, (n + 1) * ciL );
1378
1379 if( mpi_cmp_abs( A, N ) >= 0 )
1380 mpi_sub_hlp( n, N->p, A->p );
1381 else
1382 /* prevent timing attacks */
1383 mpi_sub_hlp( n, A->p, T->p );
1384}
1385
1386/*
1387 * Montgomery reduction: A = A * R^-1 mod N
1388 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001389static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001390{
Paul Bakkera755ca12011-04-24 09:11:17 +00001391 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001392 mpi U;
1393
Paul Bakker8ddb6452013-02-27 14:56:33 +01001394 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001395 U.p = &z;
1396
1397 mpi_montmul( A, &U, N, mm, T );
1398}
1399
1400/*
1401 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1402 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001403int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001404{
Paul Bakker23986e52011-04-24 08:57:21 +00001405 int ret;
1406 size_t wbits, wsize, one = 1;
1407 size_t i, j, nblimbs;
1408 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001409 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001410 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1411 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001412
1413 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001414 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001415
Paul Bakkerf6198c12012-05-16 08:02:29 +00001416 if( mpi_cmp_int( E, 0 ) < 0 )
1417 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1418
1419 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001420 * Init temps and window size
1421 */
1422 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001423 mpi_init( &RR ); mpi_init( &T );
Manuel Pégourié-Gonnard7fd620b2014-01-18 19:05:23 +01001424 mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001425 memset( W, 0, sizeof( W ) );
1426
1427 i = mpi_msb( E );
1428
1429 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1430 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1431
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001432 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1433 wsize = POLARSSL_MPI_WINDOW_SIZE;
1434
Paul Bakker5121ce52009-01-03 21:22:43 +00001435 j = N->n + 1;
1436 MPI_CHK( mpi_grow( X, j ) );
1437 MPI_CHK( mpi_grow( &W[1], j ) );
1438 MPI_CHK( mpi_grow( &T, j * 2 ) );
1439
1440 /*
Paul Bakker50546922012-05-19 08:40:49 +00001441 * Compensate for negative A (and correct at the end)
1442 */
1443 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001444 if( neg )
1445 {
1446 MPI_CHK( mpi_copy( &Apos, A ) );
1447 Apos.s = 1;
1448 A = &Apos;
1449 }
1450
1451 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001452 * If 1st call, pre-compute R^2 mod N
1453 */
1454 if( _RR == NULL || _RR->p == NULL )
1455 {
1456 MPI_CHK( mpi_lset( &RR, 1 ) );
1457 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1458 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1459
1460 if( _RR != NULL )
1461 memcpy( _RR, &RR, sizeof( mpi ) );
1462 }
1463 else
1464 memcpy( &RR, _RR, sizeof( mpi ) );
1465
1466 /*
1467 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1468 */
1469 if( mpi_cmp_mpi( A, N ) >= 0 )
Paul Bakker1dc45f12014-01-23 20:38:35 +01001470 {
1471 MPI_CHK( mpi_mod_mpi( &W[1], A, N ) );
1472 }
1473 else
1474 MPI_CHK( mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001475
1476 mpi_montmul( &W[1], &RR, N, mm, &T );
1477
1478 /*
1479 * X = R^2 * R^-1 mod N = R mod N
1480 */
1481 MPI_CHK( mpi_copy( X, &RR ) );
1482 mpi_montred( X, N, mm, &T );
1483
1484 if( wsize > 1 )
1485 {
1486 /*
1487 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1488 */
Paul Bakker23986e52011-04-24 08:57:21 +00001489 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001490
1491 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1492 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1493
1494 for( i = 0; i < wsize - 1; i++ )
1495 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakkerc3ec63d2013-10-29 16:18:35 +01001496
Paul Bakker5121ce52009-01-03 21:22:43 +00001497 /*
1498 * W[i] = W[i - 1] * W[1]
1499 */
Paul Bakker23986e52011-04-24 08:57:21 +00001500 for( i = j + 1; i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001501 {
1502 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1503 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1504
1505 mpi_montmul( &W[i], &W[1], N, mm, &T );
1506 }
1507 }
1508
1509 nblimbs = E->n;
1510 bufsize = 0;
1511 nbits = 0;
1512 wbits = 0;
1513 state = 0;
1514
1515 while( 1 )
1516 {
1517 if( bufsize == 0 )
1518 {
Paul Bakkerc3ec63d2013-10-29 16:18:35 +01001519 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001520 break;
1521
Paul Bakkerc3ec63d2013-10-29 16:18:35 +01001522 nblimbs--;
1523
Paul Bakkera755ca12011-04-24 09:11:17 +00001524 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001525 }
1526
1527 bufsize--;
1528
1529 ei = (E->p[nblimbs] >> bufsize) & 1;
1530
1531 /*
1532 * skip leading 0s
1533 */
1534 if( ei == 0 && state == 0 )
1535 continue;
1536
1537 if( ei == 0 && state == 1 )
1538 {
1539 /*
1540 * out of window, square X
1541 */
1542 mpi_montmul( X, X, N, mm, &T );
1543 continue;
1544 }
1545
1546 /*
1547 * add ei to current window
1548 */
1549 state = 2;
1550
1551 nbits++;
1552 wbits |= (ei << (wsize - nbits));
1553
1554 if( nbits == wsize )
1555 {
1556 /*
1557 * X = X^wsize R^-1 mod N
1558 */
1559 for( i = 0; i < wsize; i++ )
1560 mpi_montmul( X, X, N, mm, &T );
1561
1562 /*
1563 * X = X * W[wbits] R^-1 mod N
1564 */
1565 mpi_montmul( X, &W[wbits], N, mm, &T );
1566
1567 state--;
1568 nbits = 0;
1569 wbits = 0;
1570 }
1571 }
1572
1573 /*
1574 * process the remaining bits
1575 */
1576 for( i = 0; i < nbits; i++ )
1577 {
1578 mpi_montmul( X, X, N, mm, &T );
1579
1580 wbits <<= 1;
1581
Paul Bakker23986e52011-04-24 08:57:21 +00001582 if( (wbits & (one << wsize)) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001583 mpi_montmul( X, &W[1], N, mm, &T );
1584 }
1585
1586 /*
1587 * X = A^E * R * R^-1 mod N = A^E mod N
1588 */
1589 mpi_montred( X, N, mm, &T );
1590
Paul Bakkerf6198c12012-05-16 08:02:29 +00001591 if( neg )
1592 {
1593 X->s = -1;
Paul Bakker1dc45f12014-01-23 20:38:35 +01001594 MPI_CHK( mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001595 }
1596
Paul Bakker5121ce52009-01-03 21:22:43 +00001597cleanup:
1598
Paul Bakker23986e52011-04-24 08:57:21 +00001599 for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001600 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001601
Paul Bakkerf6198c12012-05-16 08:02:29 +00001602 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001603
Paul Bakker6995efe2014-03-31 12:08:17 +02001604 if( _RR == NULL || _RR->p == NULL )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001605 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001606
1607 return( ret );
1608}
1609
Paul Bakker5121ce52009-01-03 21:22:43 +00001610/*
1611 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1612 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001613int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001614{
Paul Bakker23986e52011-04-24 08:57:21 +00001615 int ret;
1616 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001617 mpi TG, TA, TB;
1618
Paul Bakker6c591fa2011-05-05 11:49:20 +00001619 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001620
Paul Bakker5121ce52009-01-03 21:22:43 +00001621 MPI_CHK( mpi_copy( &TA, A ) );
1622 MPI_CHK( mpi_copy( &TB, B ) );
1623
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001624 lz = mpi_lsb( &TA );
1625 lzt = mpi_lsb( &TB );
1626
1627 if ( lzt < lz )
1628 lz = lzt;
1629
1630 MPI_CHK( mpi_shift_r( &TA, lz ) );
1631 MPI_CHK( mpi_shift_r( &TB, lz ) );
1632
Paul Bakker5121ce52009-01-03 21:22:43 +00001633 TA.s = TB.s = 1;
1634
1635 while( mpi_cmp_int( &TA, 0 ) != 0 )
1636 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001637 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1638 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001639
1640 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1641 {
1642 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1643 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1644 }
1645 else
1646 {
1647 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1648 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1649 }
1650 }
1651
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001652 MPI_CHK( mpi_shift_l( &TB, lz ) );
1653 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001654
1655cleanup:
1656
Paul Bakker6c591fa2011-05-05 11:49:20 +00001657 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001658
1659 return( ret );
1660}
1661
Paul Bakker358d3252014-04-30 16:11:39 +02001662/*
1663 * Fill X with size bytes of random.
1664 *
1665 * Use a temporary bytes representation to make sure the result is the same
1666 * regardless of the platform endianness (usefull when f_rng is actually
1667 * deterministic, eg for tests).
1668 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001669int mpi_fill_random( mpi *X, size_t size,
1670 int (*f_rng)(void *, unsigned char *, size_t),
1671 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001672{
Paul Bakker23986e52011-04-24 08:57:21 +00001673 int ret;
Paul Bakker358d3252014-04-30 16:11:39 +02001674 unsigned char buf[POLARSSL_MPI_MAX_SIZE];
1675
1676 if( size > POLARSSL_MPI_MAX_SIZE )
1677 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001678
Paul Bakker39dfdac2012-02-12 17:17:27 +00001679 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001680 MPI_CHK( mpi_lset( X, 0 ) );
1681
Paul Bakker358d3252014-04-30 16:11:39 +02001682 MPI_CHK( f_rng( p_rng, buf, size ) );
1683 MPI_CHK( mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001684
1685cleanup:
1686 return( ret );
1687}
1688
Paul Bakker5121ce52009-01-03 21:22:43 +00001689/*
1690 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1691 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001692int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001693{
1694 int ret;
1695 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1696
1697 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001698 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001699
Paul Bakker6c591fa2011-05-05 11:49:20 +00001700 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1701 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1702 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001703
1704 MPI_CHK( mpi_gcd( &G, A, N ) );
1705
1706 if( mpi_cmp_int( &G, 1 ) != 0 )
1707 {
Paul Bakker40e46942009-01-03 21:51:57 +00001708 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001709 goto cleanup;
1710 }
1711
1712 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1713 MPI_CHK( mpi_copy( &TU, &TA ) );
1714 MPI_CHK( mpi_copy( &TB, N ) );
1715 MPI_CHK( mpi_copy( &TV, N ) );
1716
1717 MPI_CHK( mpi_lset( &U1, 1 ) );
1718 MPI_CHK( mpi_lset( &U2, 0 ) );
1719 MPI_CHK( mpi_lset( &V1, 0 ) );
1720 MPI_CHK( mpi_lset( &V2, 1 ) );
1721
1722 do
1723 {
1724 while( ( TU.p[0] & 1 ) == 0 )
1725 {
1726 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1727
1728 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1729 {
1730 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1731 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1732 }
1733
1734 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1735 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1736 }
1737
1738 while( ( TV.p[0] & 1 ) == 0 )
1739 {
1740 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1741
1742 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1743 {
1744 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1745 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1746 }
1747
1748 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1749 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1750 }
1751
1752 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1753 {
1754 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1755 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1756 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1757 }
1758 else
1759 {
1760 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1761 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1762 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1763 }
1764 }
1765 while( mpi_cmp_int( &TU, 0 ) != 0 );
1766
1767 while( mpi_cmp_int( &V1, 0 ) < 0 )
1768 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1769
1770 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1771 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1772
1773 MPI_CHK( mpi_copy( X, &V1 ) );
1774
1775cleanup:
1776
Paul Bakker6c591fa2011-05-05 11:49:20 +00001777 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1778 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1779 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001780
1781 return( ret );
1782}
1783
Paul Bakkerd9374b02012-11-02 11:02:58 +00001784#if defined(POLARSSL_GENPRIME)
1785
Paul Bakker5121ce52009-01-03 21:22:43 +00001786static const int small_prime[] =
1787{
1788 3, 5, 7, 11, 13, 17, 19, 23,
1789 29, 31, 37, 41, 43, 47, 53, 59,
1790 61, 67, 71, 73, 79, 83, 89, 97,
1791 101, 103, 107, 109, 113, 127, 131, 137,
1792 139, 149, 151, 157, 163, 167, 173, 179,
1793 181, 191, 193, 197, 199, 211, 223, 227,
1794 229, 233, 239, 241, 251, 257, 263, 269,
1795 271, 277, 281, 283, 293, 307, 311, 313,
1796 317, 331, 337, 347, 349, 353, 359, 367,
1797 373, 379, 383, 389, 397, 401, 409, 419,
1798 421, 431, 433, 439, 443, 449, 457, 461,
1799 463, 467, 479, 487, 491, 499, 503, 509,
1800 521, 523, 541, 547, 557, 563, 569, 571,
1801 577, 587, 593, 599, 601, 607, 613, 617,
1802 619, 631, 641, 643, 647, 653, 659, 661,
1803 673, 677, 683, 691, 701, 709, 719, 727,
1804 733, 739, 743, 751, 757, 761, 769, 773,
1805 787, 797, 809, 811, 821, 823, 827, 829,
1806 839, 853, 857, 859, 863, 877, 881, 883,
1807 887, 907, 911, 919, 929, 937, 941, 947,
1808 953, 967, 971, 977, 983, 991, 997, -103
1809};
1810
1811/*
1812 * Miller-Rabin primality test (HAC 4.24)
1813 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001814int mpi_is_prime( mpi *X,
1815 int (*f_rng)(void *, unsigned char *, size_t),
1816 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001817{
Paul Bakker23986e52011-04-24 08:57:21 +00001818 int ret, xs;
1819 size_t i, j, n, s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001820 mpi W, R, T, A, RR;
Paul Bakker5121ce52009-01-03 21:22:43 +00001821
Paul Bakker48eab262009-06-25 21:25:49 +00001822 if( mpi_cmp_int( X, 0 ) == 0 ||
1823 mpi_cmp_int( X, 1 ) == 0 )
1824 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1825
1826 if( mpi_cmp_int( X, 2 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001827 return( 0 );
1828
Paul Bakker6c591fa2011-05-05 11:49:20 +00001829 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
1830 mpi_init( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001831
1832 xs = X->s; X->s = 1;
1833
1834 /*
1835 * test trivial factors first
1836 */
1837 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001838 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001839
1840 for( i = 0; small_prime[i] > 0; i++ )
1841 {
Paul Bakkera755ca12011-04-24 09:11:17 +00001842 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001843
1844 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
1845 return( 0 );
1846
1847 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1848
1849 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001850 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001851 }
1852
1853 /*
1854 * W = |X| - 1
1855 * R = W >> lsb( W )
1856 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001857 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001858 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001859 MPI_CHK( mpi_copy( &R, &W ) );
1860 MPI_CHK( mpi_shift_r( &R, s ) );
1861
1862 i = mpi_msb( X );
1863 /*
1864 * HAC, table 4.4
1865 */
1866 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1867 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1868 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1869
1870 for( i = 0; i < n; i++ )
1871 {
1872 /*
1873 * pick a random A, 1 < A < |X| - 1
1874 */
Paul Bakker901c6562012-04-20 13:25:38 +00001875 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001876
Paul Bakkerb94081b2011-01-05 15:53:06 +00001877 if( mpi_cmp_mpi( &A, &W ) >= 0 )
1878 {
1879 j = mpi_msb( &A ) - mpi_msb( &W );
1880 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1881 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001882 A.p[0] |= 3;
1883
1884 /*
1885 * A = A^R mod |X|
1886 */
1887 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1888
1889 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1890 mpi_cmp_int( &A, 1 ) == 0 )
1891 continue;
1892
1893 j = 1;
1894 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1895 {
1896 /*
1897 * A = A * A mod |X|
1898 */
1899 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1900 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1901
1902 if( mpi_cmp_int( &A, 1 ) == 0 )
1903 break;
1904
1905 j++;
1906 }
1907
1908 /*
1909 * not prime if A != |X| - 1 or A == 1
1910 */
1911 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1912 mpi_cmp_int( &A, 1 ) == 0 )
1913 {
Paul Bakker40e46942009-01-03 21:51:57 +00001914 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001915 break;
1916 }
1917 }
1918
1919cleanup:
1920
1921 X->s = xs;
1922
Paul Bakker6c591fa2011-05-05 11:49:20 +00001923 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
1924 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001925
1926 return( ret );
1927}
1928
1929/*
1930 * Prime number generation
1931 */
Paul Bakker23986e52011-04-24 08:57:21 +00001932int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001933 int (*f_rng)(void *, unsigned char *, size_t),
1934 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001935{
Paul Bakker23986e52011-04-24 08:57:21 +00001936 int ret;
1937 size_t k, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001938 mpi Y;
1939
Paul Bakkerfe3256e2011-11-25 12:11:43 +00001940 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00001941 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001942
Paul Bakker6c591fa2011-05-05 11:49:20 +00001943 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001944
1945 n = BITS_TO_LIMBS( nbits );
1946
Paul Bakker901c6562012-04-20 13:25:38 +00001947 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001948
1949 k = mpi_msb( X );
1950 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
1951 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
1952
1953 X->p[0] |= 3;
1954
1955 if( dh_flag == 0 )
1956 {
1957 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
1958 {
Paul Bakker40e46942009-01-03 21:51:57 +00001959 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001960 goto cleanup;
1961
1962 MPI_CHK( mpi_add_int( X, X, 2 ) );
1963 }
1964 }
1965 else
1966 {
1967 MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
1968 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1969
1970 while( 1 )
1971 {
1972 if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
1973 {
1974 if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
1975 break;
1976
Paul Bakker40e46942009-01-03 21:51:57 +00001977 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001978 goto cleanup;
1979 }
1980
Paul Bakker40e46942009-01-03 21:51:57 +00001981 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001982 goto cleanup;
1983
1984 MPI_CHK( mpi_add_int( &Y, X, 1 ) );
1985 MPI_CHK( mpi_add_int( X, X, 2 ) );
1986 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1987 }
1988 }
1989
1990cleanup:
1991
Paul Bakker6c591fa2011-05-05 11:49:20 +00001992 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001993
1994 return( ret );
1995}
1996
1997#endif
1998
Paul Bakker40e46942009-01-03 21:51:57 +00001999#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002000
Paul Bakker23986e52011-04-24 08:57:21 +00002001#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002002
2003static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2004{
2005 { 693, 609, 21 },
2006 { 1764, 868, 28 },
2007 { 768454923, 542167814, 1 }
2008};
2009
Paul Bakker5121ce52009-01-03 21:22:43 +00002010/*
2011 * Checkup routine
2012 */
2013int mpi_self_test( int verbose )
2014{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002015 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002016 mpi A, E, N, X, Y, U, V;
2017
Paul Bakker6c591fa2011-05-05 11:49:20 +00002018 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2019 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002020
2021 MPI_CHK( mpi_read_string( &A, 16,
2022 "EFE021C2645FD1DC586E69184AF4A31E" \
2023 "D5F53E93B5F123FA41680867BA110131" \
2024 "944FE7952E2517337780CB0DB80E61AA" \
2025 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2026
2027 MPI_CHK( mpi_read_string( &E, 16,
2028 "B2E7EFD37075B9F03FF989C7C5051C20" \
2029 "34D2A323810251127E7BF8625A4F49A5" \
2030 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2031 "5B5C25763222FEFCCFC38B832366C29E" ) );
2032
2033 MPI_CHK( mpi_read_string( &N, 16,
2034 "0066A198186C18C10B2F5ED9B522752A" \
2035 "9830B69916E535C8F047518A889A43A5" \
2036 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2037
2038 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2039
2040 MPI_CHK( mpi_read_string( &U, 16,
2041 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2042 "9E857EA95A03512E2BAE7391688D264A" \
2043 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2044 "8001B72E848A38CAE1C65F78E56ABDEF" \
2045 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2046 "ECF677152EF804370C1A305CAF3B5BF1" \
2047 "30879B56C61DE584A0F53A2447A51E" ) );
2048
2049 if( verbose != 0 )
2050 printf( " MPI test #1 (mul_mpi): " );
2051
2052 if( mpi_cmp_mpi( &X, &U ) != 0 )
2053 {
2054 if( verbose != 0 )
2055 printf( "failed\n" );
2056
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002057 ret = 1;
2058 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002059 }
2060
2061 if( verbose != 0 )
2062 printf( "passed\n" );
2063
2064 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2065
2066 MPI_CHK( mpi_read_string( &U, 16,
2067 "256567336059E52CAE22925474705F39A94" ) );
2068
2069 MPI_CHK( mpi_read_string( &V, 16,
2070 "6613F26162223DF488E9CD48CC132C7A" \
2071 "0AC93C701B001B092E4E5B9F73BCD27B" \
2072 "9EE50D0657C77F374E903CDFA4C642" ) );
2073
2074 if( verbose != 0 )
2075 printf( " MPI test #2 (div_mpi): " );
2076
2077 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2078 mpi_cmp_mpi( &Y, &V ) != 0 )
2079 {
2080 if( verbose != 0 )
2081 printf( "failed\n" );
2082
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002083 ret = 1;
2084 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002085 }
2086
2087 if( verbose != 0 )
2088 printf( "passed\n" );
2089
2090 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2091
2092 MPI_CHK( mpi_read_string( &U, 16,
2093 "36E139AEA55215609D2816998ED020BB" \
2094 "BD96C37890F65171D948E9BC7CBAA4D9" \
2095 "325D24D6A3C12710F10A09FA08AB87" ) );
2096
2097 if( verbose != 0 )
2098 printf( " MPI test #3 (exp_mod): " );
2099
2100 if( mpi_cmp_mpi( &X, &U ) != 0 )
2101 {
2102 if( verbose != 0 )
2103 printf( "failed\n" );
2104
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002105 ret = 1;
2106 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002107 }
2108
2109 if( verbose != 0 )
2110 printf( "passed\n" );
2111
Paul Bakker5690efc2011-05-26 13:16:06 +00002112#if defined(POLARSSL_GENPRIME)
Paul Bakker5121ce52009-01-03 21:22:43 +00002113 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2114
2115 MPI_CHK( mpi_read_string( &U, 16,
2116 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2117 "C3DBA76456363A10869622EAC2DD84EC" \
2118 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2119
2120 if( verbose != 0 )
2121 printf( " MPI test #4 (inv_mod): " );
2122
2123 if( mpi_cmp_mpi( &X, &U ) != 0 )
2124 {
2125 if( verbose != 0 )
2126 printf( "failed\n" );
2127
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002128 ret = 1;
2129 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002130 }
2131
2132 if( verbose != 0 )
2133 printf( "passed\n" );
Paul Bakker5690efc2011-05-26 13:16:06 +00002134#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002135
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002136 if( verbose != 0 )
2137 printf( " MPI test #5 (simple gcd): " );
2138
2139 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2140 {
2141 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002142 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002143
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002144 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002145
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002146 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2147 {
2148 if( verbose != 0 )
2149 printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002150
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002151 ret = 1;
2152 goto cleanup;
2153 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002154 }
2155
2156 if( verbose != 0 )
2157 printf( "passed\n" );
2158
Paul Bakker5121ce52009-01-03 21:22:43 +00002159cleanup:
2160
2161 if( ret != 0 && verbose != 0 )
2162 printf( "Unexpected error, return code = %08X\n", ret );
2163
Paul Bakker6c591fa2011-05-05 11:49:20 +00002164 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2165 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002166
2167 if( verbose != 0 )
2168 printf( "\n" );
2169
2170 return( ret );
2171}
2172
2173#endif
2174
2175#endif