blob: 9544dc991a4fd40855ea78473becbe40643efb59 [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
Manuel Pégourié-Gonnard9b753052015-09-28 13:48:04 +020037#include <limits.h>
Paul Bakker5121ce52009-01-03 21:22:43 +000038#include <stdlib.h>
Paul Bakker5121ce52009-01-03 21:22:43 +000039
Paul Bakker312da332014-06-13 17:20:13 +020040/* Implementation that should never be optimized out by the compiler */
41static void polarssl_zeroize( void *v, size_t n ) {
42 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
43}
44
Paul Bakkerf9688572011-05-05 10:00:45 +000045#define ciL (sizeof(t_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000046#define biL (ciL << 3) /* bits in limb */
47#define biH (ciL << 2) /* half limb size */
48
49/*
50 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard9b753052015-09-28 13:48:04 +020051 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000052 */
Manuel Pégourié-Gonnard9b753052015-09-28 13:48:04 +020053#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
54#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000055
56/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000057 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000058 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000059void mpi_init( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000060{
Paul Bakker6c591fa2011-05-05 11:49:20 +000061 if( X == NULL )
62 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000063
Paul Bakker6c591fa2011-05-05 11:49:20 +000064 X->s = 1;
65 X->n = 0;
66 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000067}
68
69/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000070 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000071 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000072void mpi_free( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000073{
Paul Bakker6c591fa2011-05-05 11:49:20 +000074 if( X == NULL )
75 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000076
Paul Bakker6c591fa2011-05-05 11:49:20 +000077 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +000078 {
Paul Bakker312da332014-06-13 17:20:13 +020079 polarssl_zeroize( X->p, X->n * ciL );
Paul Bakker6c591fa2011-05-05 11:49:20 +000080 free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +000081 }
82
Paul Bakker6c591fa2011-05-05 11:49:20 +000083 X->s = 1;
84 X->n = 0;
85 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000086}
87
88/*
89 * Enlarge to the specified number of limbs
90 */
Paul Bakker23986e52011-04-24 08:57:21 +000091int mpi_grow( mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +000092{
Paul Bakkera755ca12011-04-24 09:11:17 +000093 t_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +000094
Paul Bakkerf9688572011-05-05 10:00:45 +000095 if( nblimbs > POLARSSL_MPI_MAX_LIMBS )
Paul Bakker69e095c2011-12-10 21:55:01 +000096 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +000097
Paul Bakker5121ce52009-01-03 21:22:43 +000098 if( X->n < nblimbs )
99 {
Paul Bakkera755ca12011-04-24 09:11:17 +0000100 if( ( p = (t_uint *) malloc( nblimbs * ciL ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000101 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000102
103 memset( p, 0, nblimbs * ciL );
104
105 if( X->p != NULL )
106 {
107 memcpy( p, X->p, X->n * ciL );
Paul Bakker312da332014-06-13 17:20:13 +0200108 polarssl_zeroize( X->p, X->n * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000109 free( X->p );
110 }
111
112 X->n = nblimbs;
113 X->p = p;
114 }
115
116 return( 0 );
117}
118
119/*
120 * Copy the contents of Y into X
121 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000122int mpi_copy( mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000123{
Paul Bakker23986e52011-04-24 08:57:21 +0000124 int ret;
125 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000126
127 if( X == Y )
128 return( 0 );
129
130 for( i = Y->n - 1; i > 0; i-- )
131 if( Y->p[i] != 0 )
132 break;
133 i++;
134
135 X->s = Y->s;
136
137 MPI_CHK( mpi_grow( X, i ) );
138
139 memset( X->p, 0, X->n * ciL );
140 memcpy( X->p, Y->p, i * ciL );
141
142cleanup:
143
144 return( ret );
145}
146
147/*
148 * Swap the contents of X and Y
149 */
150void mpi_swap( mpi *X, mpi *Y )
151{
152 mpi T;
153
154 memcpy( &T, X, sizeof( mpi ) );
155 memcpy( X, Y, sizeof( mpi ) );
156 memcpy( Y, &T, sizeof( mpi ) );
157}
158
159/*
160 * Set value from integer
161 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000162int mpi_lset( mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000163{
164 int ret;
165
166 MPI_CHK( mpi_grow( X, 1 ) );
167 memset( X->p, 0, X->n * ciL );
168
169 X->p[0] = ( z < 0 ) ? -z : z;
170 X->s = ( z < 0 ) ? -1 : 1;
171
172cleanup:
173
174 return( ret );
175}
176
177/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000178 * Get a specific bit
179 */
Paul Bakker6b906e52012-05-08 12:01:43 +0000180int mpi_get_bit( const mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000181{
182 if( X->n * biL <= pos )
183 return( 0 );
184
185 return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
186}
187
188/*
189 * Set a bit to a specific value of 0 or 1
190 */
191int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
192{
193 int ret = 0;
194 size_t off = pos / biL;
195 size_t idx = pos % biL;
196
197 if( val != 0 && val != 1 )
198 return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
199
200 if( X->n * biL <= pos )
201 {
202 if( val == 0 )
203 return ( 0 );
204
205 MPI_CHK( mpi_grow( X, off + 1 ) );
206 }
207
208 X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
209
210cleanup:
211
212 return( ret );
213}
214
215/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000216 * Return the number of least significant bits
217 */
Paul Bakker23986e52011-04-24 08:57:21 +0000218size_t mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000219{
Paul Bakker23986e52011-04-24 08:57:21 +0000220 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000221
222 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000223 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000224 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
225 return( count );
226
227 return( 0 );
228}
229
230/*
231 * Return the number of most significant bits
232 */
Paul Bakker23986e52011-04-24 08:57:21 +0000233size_t mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000234{
Paul Bakker23986e52011-04-24 08:57:21 +0000235 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000236
237 for( i = X->n - 1; i > 0; i-- )
238 if( X->p[i] != 0 )
239 break;
240
Paul Bakker23986e52011-04-24 08:57:21 +0000241 for( j = biL; j > 0; j-- )
242 if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000243 break;
244
Paul Bakker23986e52011-04-24 08:57:21 +0000245 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000246}
247
248/*
249 * Return the total size in bytes
250 */
Paul Bakker23986e52011-04-24 08:57:21 +0000251size_t mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000252{
253 return( ( mpi_msb( X ) + 7 ) >> 3 );
254}
255
256/*
257 * Convert an ASCII character to digit value
258 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000259static int mpi_get_digit( t_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000260{
261 *d = 255;
262
263 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
264 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
265 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
266
Paul Bakkera755ca12011-04-24 09:11:17 +0000267 if( *d >= (t_uint) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000268 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000269
270 return( 0 );
271}
272
273/*
274 * Import from an ASCII string
275 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000276int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000277{
Paul Bakker23986e52011-04-24 08:57:21 +0000278 int ret;
279 size_t i, j, slen, n;
Paul Bakkera755ca12011-04-24 09:11:17 +0000280 t_uint d;
Paul Bakker5121ce52009-01-03 21:22:43 +0000281 mpi T;
282
283 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000284 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000285
Paul Bakker6c591fa2011-05-05 11:49:20 +0000286 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000287
Paul Bakkerff60ee62010-03-16 21:09:09 +0000288 slen = strlen( s );
289
Paul Bakker5121ce52009-01-03 21:22:43 +0000290 if( radix == 16 )
291 {
Manuel Pégourié-Gonnard9b753052015-09-28 13:48:04 +0200292 if( slen > SIZE_T_MAX >> 2 )
293 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
294
Paul Bakkerff60ee62010-03-16 21:09:09 +0000295 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000296
297 MPI_CHK( mpi_grow( X, n ) );
298 MPI_CHK( mpi_lset( X, 0 ) );
299
Paul Bakker23986e52011-04-24 08:57:21 +0000300 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000301 {
Paul Bakker23986e52011-04-24 08:57:21 +0000302 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000303 {
304 X->s = -1;
305 break;
306 }
307
Paul Bakker23986e52011-04-24 08:57:21 +0000308 MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000309 X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
310 }
311 }
312 else
313 {
314 MPI_CHK( mpi_lset( X, 0 ) );
315
Paul Bakkerff60ee62010-03-16 21:09:09 +0000316 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000317 {
318 if( i == 0 && s[i] == '-' )
319 {
320 X->s = -1;
321 continue;
322 }
323
324 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
325 MPI_CHK( mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000326
327 if( X->s == 1 )
328 {
329 MPI_CHK( mpi_add_int( X, &T, d ) );
330 }
331 else
332 {
333 MPI_CHK( mpi_sub_int( X, &T, d ) );
334 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000335 }
336 }
337
338cleanup:
339
Paul Bakker6c591fa2011-05-05 11:49:20 +0000340 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000341
342 return( ret );
343}
344
345/*
346 * Helper to write the digits high-order first
347 */
348static int mpi_write_hlp( mpi *X, int radix, char **p )
349{
350 int ret;
Paul Bakkera755ca12011-04-24 09:11:17 +0000351 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000352
353 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000354 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000355
356 MPI_CHK( mpi_mod_int( &r, X, radix ) );
357 MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
358
359 if( mpi_cmp_int( X, 0 ) != 0 )
360 MPI_CHK( mpi_write_hlp( X, radix, p ) );
361
362 if( r < 10 )
363 *(*p)++ = (char)( r + 0x30 );
364 else
365 *(*p)++ = (char)( r + 0x37 );
366
367cleanup:
368
369 return( ret );
370}
371
372/*
373 * Export into an ASCII string
374 */
Paul Bakker23986e52011-04-24 08:57:21 +0000375int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000376{
Paul Bakker23986e52011-04-24 08:57:21 +0000377 int ret = 0;
378 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 char *p;
380 mpi T;
381
382 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000383 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000384
385 n = mpi_msb( X );
386 if( radix >= 4 ) n >>= 1;
387 if( radix >= 16 ) n >>= 1;
388 n += 3;
389
390 if( *slen < n )
391 {
392 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000393 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000394 }
395
396 p = s;
Paul Bakker6c591fa2011-05-05 11:49:20 +0000397 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000398
399 if( X->s == -1 )
400 *p++ = '-';
401
402 if( radix == 16 )
403 {
Paul Bakker23986e52011-04-24 08:57:21 +0000404 int c;
405 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000406
Paul Bakker23986e52011-04-24 08:57:21 +0000407 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000408 {
Paul Bakker23986e52011-04-24 08:57:21 +0000409 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000410 {
Paul Bakker23986e52011-04-24 08:57:21 +0000411 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000412
Paul Bakker23986e52011-04-24 08:57:21 +0000413 if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000414 continue;
415
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000416 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000417 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000418 k = 1;
419 }
420 }
421 }
422 else
423 {
424 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000425
426 if( T.s == -1 )
427 T.s = 1;
428
Paul Bakker5121ce52009-01-03 21:22:43 +0000429 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
430 }
431
432 *p++ = '\0';
433 *slen = p - s;
434
435cleanup:
436
Paul Bakker6c591fa2011-05-05 11:49:20 +0000437 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000438
439 return( ret );
440}
441
Paul Bakker335db3f2011-04-25 15:28:35 +0000442#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000443/*
444 * Read X from an opened file
445 */
446int mpi_read_file( mpi *X, int radix, FILE *fin )
447{
Paul Bakkera755ca12011-04-24 09:11:17 +0000448 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000449 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000450 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000451 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000452 * Buffer should have space for (short) label and decimal formatted MPI,
453 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000454 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000455 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000456
457 memset( s, 0, sizeof( s ) );
458 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000459 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000460
461 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000462 if( slen == sizeof( s ) - 2 )
463 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
464
Paul Bakker5121ce52009-01-03 21:22:43 +0000465 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
466 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
467
468 p = s + slen;
469 while( --p >= s )
470 if( mpi_get_digit( &d, radix, *p ) != 0 )
471 break;
472
473 return( mpi_read_string( X, radix, p + 1 ) );
474}
475
476/*
477 * Write X into an opened file (or stdout if fout == NULL)
478 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000479int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000480{
Paul Bakker23986e52011-04-24 08:57:21 +0000481 int ret;
482 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000483 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000484 * Buffer should have space for (short) label and decimal formatted MPI,
485 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000486 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000487 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000488
489 n = sizeof( s );
490 memset( s, 0, n );
491 n -= 2;
492
Paul Bakker23986e52011-04-24 08:57:21 +0000493 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494
495 if( p == NULL ) p = "";
496
497 plen = strlen( p );
498 slen = strlen( s );
499 s[slen++] = '\r';
500 s[slen++] = '\n';
501
502 if( fout != NULL )
503 {
504 if( fwrite( p, 1, plen, fout ) != plen ||
505 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000506 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000507 }
508 else
509 printf( "%s%s", p, s );
510
511cleanup:
512
513 return( ret );
514}
Paul Bakker335db3f2011-04-25 15:28:35 +0000515#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000516
517/*
518 * Import X from unsigned binary data, big endian
519 */
Paul Bakker23986e52011-04-24 08:57:21 +0000520int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000521{
Paul Bakker23986e52011-04-24 08:57:21 +0000522 int ret;
523 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000524
525 for( n = 0; n < buflen; n++ )
526 if( buf[n] != 0 )
527 break;
528
529 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
530 MPI_CHK( mpi_lset( X, 0 ) );
531
Paul Bakker23986e52011-04-24 08:57:21 +0000532 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000533 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000534
535cleanup:
536
537 return( ret );
538}
539
540/*
541 * Export X into unsigned binary data, big endian
542 */
Paul Bakker23986e52011-04-24 08:57:21 +0000543int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000544{
Paul Bakker23986e52011-04-24 08:57:21 +0000545 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000546
547 n = mpi_size( X );
548
549 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000550 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000551
552 memset( buf, 0, buflen );
553
554 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
555 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
556
557 return( 0 );
558}
559
560/*
561 * Left-shift: X <<= count
562 */
Paul Bakker23986e52011-04-24 08:57:21 +0000563int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000564{
Paul Bakker23986e52011-04-24 08:57:21 +0000565 int ret;
566 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000567 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000568
569 v0 = count / (biL );
570 t1 = count & (biL - 1);
571
572 i = mpi_msb( X ) + count;
573
Paul Bakkerf9688572011-05-05 10:00:45 +0000574 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000575 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
576
577 ret = 0;
578
579 /*
580 * shift by count / limb_size
581 */
582 if( v0 > 0 )
583 {
Paul Bakker23986e52011-04-24 08:57:21 +0000584 for( i = X->n; i > v0; i-- )
585 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000586
Paul Bakker23986e52011-04-24 08:57:21 +0000587 for( ; i > 0; i-- )
588 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000589 }
590
591 /*
592 * shift by count % limb_size
593 */
594 if( t1 > 0 )
595 {
596 for( i = v0; i < X->n; i++ )
597 {
598 r1 = X->p[i] >> (biL - t1);
599 X->p[i] <<= t1;
600 X->p[i] |= r0;
601 r0 = r1;
602 }
603 }
604
605cleanup:
606
607 return( ret );
608}
609
610/*
611 * Right-shift: X >>= count
612 */
Paul Bakker23986e52011-04-24 08:57:21 +0000613int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000614{
Paul Bakker23986e52011-04-24 08:57:21 +0000615 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000616 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000617
618 v0 = count / biL;
619 v1 = count & (biL - 1);
620
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100621 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
622 return mpi_lset( X, 0 );
623
Paul Bakker5121ce52009-01-03 21:22:43 +0000624 /*
625 * shift by count / limb_size
626 */
627 if( v0 > 0 )
628 {
629 for( i = 0; i < X->n - v0; i++ )
630 X->p[i] = X->p[i + v0];
631
632 for( ; i < X->n; i++ )
633 X->p[i] = 0;
634 }
635
636 /*
637 * shift by count % limb_size
638 */
639 if( v1 > 0 )
640 {
Paul Bakker23986e52011-04-24 08:57:21 +0000641 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000642 {
Paul Bakker23986e52011-04-24 08:57:21 +0000643 r1 = X->p[i - 1] << (biL - v1);
644 X->p[i - 1] >>= v1;
645 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000646 r0 = r1;
647 }
648 }
649
650 return( 0 );
651}
652
653/*
654 * Compare unsigned values
655 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000656int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000657{
Paul Bakker23986e52011-04-24 08:57:21 +0000658 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000659
Paul Bakker23986e52011-04-24 08:57:21 +0000660 for( i = X->n; i > 0; i-- )
661 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000662 break;
663
Paul Bakker23986e52011-04-24 08:57:21 +0000664 for( j = Y->n; j > 0; j-- )
665 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000666 break;
667
Paul Bakker23986e52011-04-24 08:57:21 +0000668 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000669 return( 0 );
670
671 if( i > j ) return( 1 );
672 if( j > i ) return( -1 );
673
Paul Bakker23986e52011-04-24 08:57:21 +0000674 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000675 {
Paul Bakker23986e52011-04-24 08:57:21 +0000676 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
677 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000678 }
679
680 return( 0 );
681}
682
683/*
684 * Compare signed values
685 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000686int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000687{
Paul Bakker23986e52011-04-24 08:57:21 +0000688 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000689
Paul Bakker23986e52011-04-24 08:57:21 +0000690 for( i = X->n; i > 0; i-- )
691 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000692 break;
693
Paul Bakker23986e52011-04-24 08:57:21 +0000694 for( j = Y->n; j > 0; j-- )
695 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000696 break;
697
Paul Bakker23986e52011-04-24 08:57:21 +0000698 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000699 return( 0 );
700
701 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000702 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000703
704 if( X->s > 0 && Y->s < 0 ) return( 1 );
705 if( Y->s > 0 && X->s < 0 ) return( -1 );
706
Paul Bakker23986e52011-04-24 08:57:21 +0000707 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000708 {
Paul Bakker23986e52011-04-24 08:57:21 +0000709 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
710 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000711 }
712
713 return( 0 );
714}
715
716/*
717 * Compare signed values
718 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000719int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000720{
721 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000722 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000723
724 *p = ( z < 0 ) ? -z : z;
725 Y.s = ( z < 0 ) ? -1 : 1;
726 Y.n = 1;
727 Y.p = p;
728
729 return( mpi_cmp_mpi( X, &Y ) );
730}
731
732/*
733 * Unsigned addition: X = |A| + |B| (HAC 14.7)
734 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000735int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000736{
Paul Bakker23986e52011-04-24 08:57:21 +0000737 int ret;
738 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000739 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000740
741 if( X == B )
742 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000743 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000744 }
745
746 if( X != A )
747 MPI_CHK( mpi_copy( X, A ) );
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000748
749 /*
750 * X should always be positive as a result of unsigned additions.
751 */
752 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000753
Paul Bakker23986e52011-04-24 08:57:21 +0000754 for( j = B->n; j > 0; j-- )
755 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000756 break;
757
Paul Bakker23986e52011-04-24 08:57:21 +0000758 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000759
760 o = B->p; p = X->p; c = 0;
761
Paul Bakker23986e52011-04-24 08:57:21 +0000762 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000763 {
764 *p += c; c = ( *p < c );
765 *p += *o; c += ( *p < *o );
766 }
767
768 while( c != 0 )
769 {
770 if( i >= X->n )
771 {
772 MPI_CHK( mpi_grow( X, i + 1 ) );
773 p = X->p + i;
774 }
775
Paul Bakker2d319fd2012-09-16 21:34:26 +0000776 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000777 }
778
779cleanup:
780
781 return( ret );
782}
783
784/*
785 * Helper for mpi substraction
786 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000787static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000788{
Paul Bakker23986e52011-04-24 08:57:21 +0000789 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000790 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000791
792 for( i = c = 0; i < n; i++, s++, d++ )
793 {
794 z = ( *d < c ); *d -= c;
795 c = ( *d < *s ) + z; *d -= *s;
796 }
797
798 while( c != 0 )
799 {
800 z = ( *d < c ); *d -= c;
801 c = z; i++; d++;
802 }
803}
804
805/*
806 * Unsigned substraction: X = |A| - |B| (HAC 14.9)
807 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000808int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000809{
810 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000811 int ret;
812 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000813
814 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000815 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000816
Paul Bakker6c591fa2011-05-05 11:49:20 +0000817 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000818
819 if( X == B )
820 {
821 MPI_CHK( mpi_copy( &TB, B ) );
822 B = &TB;
823 }
824
825 if( X != A )
826 MPI_CHK( mpi_copy( X, A ) );
827
Paul Bakker1ef7a532009-06-20 10:50:55 +0000828 /*
829 * X should always be positive as a result of unsigned substractions.
830 */
831 X->s = 1;
832
Paul Bakker5121ce52009-01-03 21:22:43 +0000833 ret = 0;
834
Paul Bakker23986e52011-04-24 08:57:21 +0000835 for( n = B->n; n > 0; n-- )
836 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000837 break;
838
Paul Bakker23986e52011-04-24 08:57:21 +0000839 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000840
841cleanup:
842
Paul Bakker6c591fa2011-05-05 11:49:20 +0000843 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000844
845 return( ret );
846}
847
848/*
849 * Signed addition: X = A + B
850 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000851int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000852{
853 int ret, s = A->s;
854
855 if( A->s * B->s < 0 )
856 {
857 if( mpi_cmp_abs( A, B ) >= 0 )
858 {
859 MPI_CHK( mpi_sub_abs( X, A, B ) );
860 X->s = s;
861 }
862 else
863 {
864 MPI_CHK( mpi_sub_abs( X, B, A ) );
865 X->s = -s;
866 }
867 }
868 else
869 {
870 MPI_CHK( mpi_add_abs( X, A, B ) );
871 X->s = s;
872 }
873
874cleanup:
875
876 return( ret );
877}
878
879/*
880 * Signed substraction: X = A - B
881 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000882int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000883{
884 int ret, s = A->s;
885
886 if( A->s * B->s > 0 )
887 {
888 if( mpi_cmp_abs( A, B ) >= 0 )
889 {
890 MPI_CHK( mpi_sub_abs( X, A, B ) );
891 X->s = s;
892 }
893 else
894 {
895 MPI_CHK( mpi_sub_abs( X, B, A ) );
896 X->s = -s;
897 }
898 }
899 else
900 {
901 MPI_CHK( mpi_add_abs( X, A, B ) );
902 X->s = s;
903 }
904
905cleanup:
906
907 return( ret );
908}
909
910/*
911 * Signed addition: X = A + b
912 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000913int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000914{
915 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000916 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000917
918 p[0] = ( b < 0 ) ? -b : b;
919 _B.s = ( b < 0 ) ? -1 : 1;
920 _B.n = 1;
921 _B.p = p;
922
923 return( mpi_add_mpi( X, A, &_B ) );
924}
925
926/*
927 * Signed substraction: X = A - b
928 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000929int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000930{
931 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000932 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000933
934 p[0] = ( b < 0 ) ? -b : b;
935 _B.s = ( b < 0 ) ? -1 : 1;
936 _B.n = 1;
937 _B.p = p;
938
939 return( mpi_sub_mpi( X, A, &_B ) );
940}
941
942/*
943 * Helper for mpi multiplication
Paul Bakker52b845b2013-06-14 11:36:56 +0200944 */
945static
946#if defined(__APPLE__) && defined(__arm__)
947/*
948 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
949 * appears to need this to prevent bad ARM code generation at -O3.
950 */
951__attribute__ ((noinline))
952#endif
953void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000954{
Paul Bakkera755ca12011-04-24 09:11:17 +0000955 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000956
957#if defined(MULADDC_HUIT)
958 for( ; i >= 8; i -= 8 )
959 {
960 MULADDC_INIT
961 MULADDC_HUIT
962 MULADDC_STOP
963 }
964
965 for( ; i > 0; i-- )
966 {
967 MULADDC_INIT
968 MULADDC_CORE
969 MULADDC_STOP
970 }
971#else
972 for( ; i >= 16; i -= 16 )
973 {
974 MULADDC_INIT
975 MULADDC_CORE MULADDC_CORE
976 MULADDC_CORE MULADDC_CORE
977 MULADDC_CORE MULADDC_CORE
978 MULADDC_CORE MULADDC_CORE
979
980 MULADDC_CORE MULADDC_CORE
981 MULADDC_CORE MULADDC_CORE
982 MULADDC_CORE MULADDC_CORE
983 MULADDC_CORE MULADDC_CORE
984 MULADDC_STOP
985 }
986
987 for( ; i >= 8; i -= 8 )
988 {
989 MULADDC_INIT
990 MULADDC_CORE MULADDC_CORE
991 MULADDC_CORE MULADDC_CORE
992
993 MULADDC_CORE MULADDC_CORE
994 MULADDC_CORE MULADDC_CORE
995 MULADDC_STOP
996 }
997
998 for( ; i > 0; i-- )
999 {
1000 MULADDC_INIT
1001 MULADDC_CORE
1002 MULADDC_STOP
1003 }
1004#endif
1005
1006 t++;
1007
1008 do {
1009 *d += c; c = ( *d < c ); d++;
1010 }
1011 while( c != 0 );
1012}
1013
1014/*
1015 * Baseline multiplication: X = A * B (HAC 14.12)
1016 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001017int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001018{
Paul Bakker23986e52011-04-24 08:57:21 +00001019 int ret;
1020 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001021 mpi TA, TB;
1022
Paul Bakker6c591fa2011-05-05 11:49:20 +00001023 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001024
1025 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1026 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1027
Paul Bakker23986e52011-04-24 08:57:21 +00001028 for( i = A->n; i > 0; i-- )
1029 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001030 break;
1031
Paul Bakker23986e52011-04-24 08:57:21 +00001032 for( j = B->n; j > 0; j-- )
1033 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001034 break;
1035
Paul Bakker23986e52011-04-24 08:57:21 +00001036 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001037 MPI_CHK( mpi_lset( X, 0 ) );
1038
Paul Bakker23986e52011-04-24 08:57:21 +00001039 for( i++; j > 0; j-- )
1040 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001041
1042 X->s = A->s * B->s;
1043
1044cleanup:
1045
Paul Bakker6c591fa2011-05-05 11:49:20 +00001046 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001047
1048 return( ret );
1049}
1050
1051/*
1052 * Baseline multiplication: X = A * b
1053 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001054int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001055{
1056 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001057 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001058
1059 _B.s = 1;
1060 _B.n = 1;
1061 _B.p = p;
1062 p[0] = b;
1063
1064 return( mpi_mul_mpi( X, A, &_B ) );
1065}
1066
1067/*
1068 * Division by mpi: A = Q * B + R (HAC 14.20)
1069 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001070int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001071{
Paul Bakker23986e52011-04-24 08:57:21 +00001072 int ret;
1073 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001074 mpi X, Y, Z, T1, T2;
1075
1076 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001077 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001078
Paul Bakker6c591fa2011-05-05 11:49:20 +00001079 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1080 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001081
1082 if( mpi_cmp_abs( A, B ) < 0 )
1083 {
1084 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1085 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1086 return( 0 );
1087 }
1088
1089 MPI_CHK( mpi_copy( &X, A ) );
1090 MPI_CHK( mpi_copy( &Y, B ) );
1091 X.s = Y.s = 1;
1092
1093 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1094 MPI_CHK( mpi_lset( &Z, 0 ) );
1095 MPI_CHK( mpi_grow( &T1, 2 ) );
1096 MPI_CHK( mpi_grow( &T2, 3 ) );
1097
1098 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001099 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001100 {
1101 k = biL - 1 - k;
1102 MPI_CHK( mpi_shift_l( &X, k ) );
1103 MPI_CHK( mpi_shift_l( &Y, k ) );
1104 }
1105 else k = 0;
1106
1107 n = X.n - 1;
1108 t = Y.n - 1;
Paul Bakkerc110d022012-10-19 12:15:08 +00001109 MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001110
1111 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1112 {
1113 Z.p[n - t]++;
Paul Bakker78e81962013-12-31 11:16:03 +01001114 MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001115 }
Paul Bakker78e81962013-12-31 11:16:03 +01001116 MPI_CHK( mpi_shift_r( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001117
1118 for( i = n; i > t ; i-- )
1119 {
1120 if( X.p[i] >= Y.p[t] )
1121 Z.p[i - t - 1] = ~0;
1122 else
1123 {
Manuel Pégourié-Gonnard57291a72014-03-14 09:21:20 +01001124 /*
Manuel Pégourié-Gonnarda9f86e02014-03-14 18:23:26 +01001125 * The version of Clang shipped by Apple with Mavericks around
1126 * 2014-03 can't handle 128-bit division properly. Disable
1127 * 128-bits division for this version. Let's be optimistic and
1128 * assume it'll be fixed in the next minor version (next
1129 * patchlevel is probably a bit too optimistic).
Manuel Pégourié-Gonnard57291a72014-03-14 09:21:20 +01001130 */
Manuel Pégourié-Gonnarda9f86e02014-03-14 18:23:26 +01001131#if defined(POLARSSL_HAVE_UDBL) && \
1132 ! ( defined(__x86_64__) && defined(__APPLE__) && \
1133 defined(__clang_major__) && __clang_major__ == 5 && \
1134 defined(__clang_minor__) && __clang_minor__ == 0 )
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001135 t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001136
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001137 r = (t_udbl) X.p[i] << biL;
1138 r |= (t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001139 r /= Y.p[t];
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001140 if( r > ((t_udbl) 1 << biL) - 1)
1141 r = ((t_udbl) 1 << biL) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001142
Paul Bakkera755ca12011-04-24 09:11:17 +00001143 Z.p[i - t - 1] = (t_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001144#else
1145 /*
1146 * __udiv_qrnnd_c, from gmp/longlong.h
1147 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001148 t_uint q0, q1, r0, r1;
1149 t_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001150
1151 d = Y.p[t];
1152 d0 = ( d << biH ) >> biH;
1153 d1 = ( d >> biH );
1154
1155 q1 = X.p[i] / d1;
1156 r1 = X.p[i] - d1 * q1;
1157 r1 <<= biH;
1158 r1 |= ( X.p[i - 1] >> biH );
1159
1160 m = q1 * d0;
1161 if( r1 < m )
1162 {
1163 q1--, r1 += d;
1164 while( r1 >= d && r1 < m )
1165 q1--, r1 += d;
1166 }
1167 r1 -= m;
1168
1169 q0 = r1 / d1;
1170 r0 = r1 - d1 * q0;
1171 r0 <<= biH;
1172 r0 |= ( X.p[i - 1] << biH ) >> biH;
1173
1174 m = q0 * d0;
1175 if( r0 < m )
1176 {
1177 q0--, r0 += d;
1178 while( r0 >= d && r0 < m )
1179 q0--, r0 += d;
1180 }
1181 r0 -= m;
1182
1183 Z.p[i - t - 1] = ( q1 << biH ) | q0;
1184#endif
1185 }
1186
1187 Z.p[i - t - 1]++;
1188 do
1189 {
1190 Z.p[i - t - 1]--;
1191
1192 MPI_CHK( mpi_lset( &T1, 0 ) );
1193 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1194 T1.p[1] = Y.p[t];
1195 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1196
1197 MPI_CHK( mpi_lset( &T2, 0 ) );
1198 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1199 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1200 T2.p[2] = X.p[i];
1201 }
1202 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1203
1204 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1205 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1206 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1207
1208 if( mpi_cmp_int( &X, 0 ) < 0 )
1209 {
1210 MPI_CHK( mpi_copy( &T1, &Y ) );
1211 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1212 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1213 Z.p[i - t - 1]--;
1214 }
1215 }
1216
1217 if( Q != NULL )
1218 {
Paul Bakker78e81962013-12-31 11:16:03 +01001219 MPI_CHK( mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001220 Q->s = A->s * B->s;
1221 }
1222
1223 if( R != NULL )
1224 {
Paul Bakker78e81962013-12-31 11:16:03 +01001225 MPI_CHK( mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001226 X.s = A->s;
Paul Bakker78e81962013-12-31 11:16:03 +01001227 MPI_CHK( mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001228
Paul Bakker5121ce52009-01-03 21:22:43 +00001229 if( mpi_cmp_int( R, 0 ) == 0 )
1230 R->s = 1;
1231 }
1232
1233cleanup:
1234
Paul Bakker6c591fa2011-05-05 11:49:20 +00001235 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1236 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001237
1238 return( ret );
1239}
1240
1241/*
1242 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001243 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001244int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001245{
1246 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001247 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001248
1249 p[0] = ( b < 0 ) ? -b : b;
1250 _B.s = ( b < 0 ) ? -1 : 1;
1251 _B.n = 1;
1252 _B.p = p;
1253
1254 return( mpi_div_mpi( Q, R, A, &_B ) );
1255}
1256
1257/*
1258 * Modulo: R = A mod B
1259 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001260int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001261{
1262 int ret;
1263
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001264 if( mpi_cmp_int( B, 0 ) < 0 )
1265 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1266
Paul Bakker5121ce52009-01-03 21:22:43 +00001267 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1268
1269 while( mpi_cmp_int( R, 0 ) < 0 )
1270 MPI_CHK( mpi_add_mpi( R, R, B ) );
1271
1272 while( mpi_cmp_mpi( R, B ) >= 0 )
1273 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1274
1275cleanup:
1276
1277 return( ret );
1278}
1279
1280/*
1281 * Modulo: r = A mod b
1282 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001283int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001284{
Paul Bakker23986e52011-04-24 08:57:21 +00001285 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001286 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001287
1288 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001289 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001290
1291 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001292 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001293
1294 /*
1295 * handle trivial cases
1296 */
1297 if( b == 1 )
1298 {
1299 *r = 0;
1300 return( 0 );
1301 }
1302
1303 if( b == 2 )
1304 {
1305 *r = A->p[0] & 1;
1306 return( 0 );
1307 }
1308
1309 /*
1310 * general case
1311 */
Paul Bakker23986e52011-04-24 08:57:21 +00001312 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001313 {
Paul Bakker23986e52011-04-24 08:57:21 +00001314 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001315 y = ( y << biH ) | ( x >> biH );
1316 z = y / b;
1317 y -= z * b;
1318
1319 x <<= biH;
1320 y = ( y << biH ) | ( x >> biH );
1321 z = y / b;
1322 y -= z * b;
1323 }
1324
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001325 /*
1326 * If A is negative, then the current y represents a negative value.
1327 * Flipping it to the positive side.
1328 */
1329 if( A->s < 0 && y != 0 )
1330 y = b - y;
1331
Paul Bakker5121ce52009-01-03 21:22:43 +00001332 *r = y;
1333
1334 return( 0 );
1335}
1336
1337/*
1338 * Fast Montgomery initialization (thanks to Tom St Denis)
1339 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001340static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001341{
Paul Bakkera755ca12011-04-24 09:11:17 +00001342 t_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnard397858b2014-03-11 13:47:05 +01001343 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001344
1345 x = m0;
1346 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001347
Manuel Pégourié-Gonnard397858b2014-03-11 13:47:05 +01001348 for( i = biL; i >= 8; i /= 2 )
1349 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001350
1351 *mm = ~x + 1;
1352}
1353
1354/*
1355 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1356 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001357static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001358{
Paul Bakker23986e52011-04-24 08:57:21 +00001359 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001360 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001361
1362 memset( T->p, 0, T->n * ciL );
1363
1364 d = T->p;
1365 n = N->n;
1366 m = ( B->n < n ) ? B->n : n;
1367
1368 for( i = 0; i < n; i++ )
1369 {
1370 /*
1371 * T = (T + u0*B + u1*N) / 2^biL
1372 */
1373 u0 = A->p[i];
1374 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1375
1376 mpi_mul_hlp( m, B->p, d, u0 );
1377 mpi_mul_hlp( n, N->p, d, u1 );
1378
1379 *d++ = u0; d[n + 1] = 0;
1380 }
1381
1382 memcpy( A->p, d, (n + 1) * ciL );
1383
1384 if( mpi_cmp_abs( A, N ) >= 0 )
1385 mpi_sub_hlp( n, N->p, A->p );
1386 else
1387 /* prevent timing attacks */
1388 mpi_sub_hlp( n, A->p, T->p );
1389}
1390
1391/*
1392 * Montgomery reduction: A = A * R^-1 mod N
1393 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001394static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001395{
Paul Bakkera755ca12011-04-24 09:11:17 +00001396 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001397 mpi U;
1398
Paul Bakker8ddb6452013-02-27 14:56:33 +01001399 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001400 U.p = &z;
1401
1402 mpi_montmul( A, &U, N, mm, T );
1403}
1404
1405/*
1406 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1407 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001408int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001409{
Paul Bakker23986e52011-04-24 08:57:21 +00001410 int ret;
1411 size_t wbits, wsize, one = 1;
1412 size_t i, j, nblimbs;
1413 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001414 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001415 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1416 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001417
1418 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001419 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001420
Paul Bakkerf6198c12012-05-16 08:02:29 +00001421 if( mpi_cmp_int( E, 0 ) < 0 )
1422 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1423
1424 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001425 * Init temps and window size
1426 */
1427 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001428 mpi_init( &RR ); mpi_init( &T );
Manuel Pégourié-Gonnard7fd620b2014-01-18 19:05:23 +01001429 mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001430 memset( W, 0, sizeof( W ) );
1431
1432 i = mpi_msb( E );
1433
1434 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1435 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1436
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001437 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1438 wsize = POLARSSL_MPI_WINDOW_SIZE;
1439
Paul Bakker5121ce52009-01-03 21:22:43 +00001440 j = N->n + 1;
1441 MPI_CHK( mpi_grow( X, j ) );
1442 MPI_CHK( mpi_grow( &W[1], j ) );
1443 MPI_CHK( mpi_grow( &T, j * 2 ) );
1444
1445 /*
Paul Bakker50546922012-05-19 08:40:49 +00001446 * Compensate for negative A (and correct at the end)
1447 */
1448 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001449 if( neg )
1450 {
1451 MPI_CHK( mpi_copy( &Apos, A ) );
1452 Apos.s = 1;
1453 A = &Apos;
1454 }
1455
1456 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001457 * If 1st call, pre-compute R^2 mod N
1458 */
1459 if( _RR == NULL || _RR->p == NULL )
1460 {
1461 MPI_CHK( mpi_lset( &RR, 1 ) );
1462 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1463 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1464
1465 if( _RR != NULL )
1466 memcpy( _RR, &RR, sizeof( mpi ) );
1467 }
1468 else
1469 memcpy( &RR, _RR, sizeof( mpi ) );
1470
1471 /*
1472 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1473 */
1474 if( mpi_cmp_mpi( A, N ) >= 0 )
Paul Bakker1dc45f12014-01-23 20:38:35 +01001475 {
1476 MPI_CHK( mpi_mod_mpi( &W[1], A, N ) );
1477 }
1478 else
1479 MPI_CHK( mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001480
1481 mpi_montmul( &W[1], &RR, N, mm, &T );
1482
1483 /*
1484 * X = R^2 * R^-1 mod N = R mod N
1485 */
1486 MPI_CHK( mpi_copy( X, &RR ) );
1487 mpi_montred( X, N, mm, &T );
1488
1489 if( wsize > 1 )
1490 {
1491 /*
1492 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1493 */
Paul Bakker23986e52011-04-24 08:57:21 +00001494 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001495
1496 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1497 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1498
1499 for( i = 0; i < wsize - 1; i++ )
1500 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakkerc3ec63d2013-10-29 16:18:35 +01001501
Paul Bakker5121ce52009-01-03 21:22:43 +00001502 /*
1503 * W[i] = W[i - 1] * W[1]
1504 */
Paul Bakker23986e52011-04-24 08:57:21 +00001505 for( i = j + 1; i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001506 {
1507 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1508 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1509
1510 mpi_montmul( &W[i], &W[1], N, mm, &T );
1511 }
1512 }
1513
1514 nblimbs = E->n;
1515 bufsize = 0;
1516 nbits = 0;
1517 wbits = 0;
1518 state = 0;
1519
1520 while( 1 )
1521 {
1522 if( bufsize == 0 )
1523 {
Paul Bakkerc3ec63d2013-10-29 16:18:35 +01001524 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001525 break;
1526
Paul Bakkerc3ec63d2013-10-29 16:18:35 +01001527 nblimbs--;
1528
Paul Bakkera755ca12011-04-24 09:11:17 +00001529 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001530 }
1531
1532 bufsize--;
1533
1534 ei = (E->p[nblimbs] >> bufsize) & 1;
1535
1536 /*
1537 * skip leading 0s
1538 */
1539 if( ei == 0 && state == 0 )
1540 continue;
1541
1542 if( ei == 0 && state == 1 )
1543 {
1544 /*
1545 * out of window, square X
1546 */
1547 mpi_montmul( X, X, N, mm, &T );
1548 continue;
1549 }
1550
1551 /*
1552 * add ei to current window
1553 */
1554 state = 2;
1555
1556 nbits++;
1557 wbits |= (ei << (wsize - nbits));
1558
1559 if( nbits == wsize )
1560 {
1561 /*
1562 * X = X^wsize R^-1 mod N
1563 */
1564 for( i = 0; i < wsize; i++ )
1565 mpi_montmul( X, X, N, mm, &T );
1566
1567 /*
1568 * X = X * W[wbits] R^-1 mod N
1569 */
1570 mpi_montmul( X, &W[wbits], N, mm, &T );
1571
1572 state--;
1573 nbits = 0;
1574 wbits = 0;
1575 }
1576 }
1577
1578 /*
1579 * process the remaining bits
1580 */
1581 for( i = 0; i < nbits; i++ )
1582 {
1583 mpi_montmul( X, X, N, mm, &T );
1584
1585 wbits <<= 1;
1586
Paul Bakker23986e52011-04-24 08:57:21 +00001587 if( (wbits & (one << wsize)) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001588 mpi_montmul( X, &W[1], N, mm, &T );
1589 }
1590
1591 /*
1592 * X = A^E * R * R^-1 mod N = A^E mod N
1593 */
1594 mpi_montred( X, N, mm, &T );
1595
Paul Bakkerf6198c12012-05-16 08:02:29 +00001596 if( neg )
1597 {
1598 X->s = -1;
Paul Bakker1dc45f12014-01-23 20:38:35 +01001599 MPI_CHK( mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001600 }
1601
Paul Bakker5121ce52009-01-03 21:22:43 +00001602cleanup:
1603
Paul Bakker23986e52011-04-24 08:57:21 +00001604 for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001605 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001606
Paul Bakkerf6198c12012-05-16 08:02:29 +00001607 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001608
Paul Bakker6995efe2014-03-31 12:08:17 +02001609 if( _RR == NULL || _RR->p == NULL )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001610 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001611
1612 return( ret );
1613}
1614
Paul Bakker5121ce52009-01-03 21:22:43 +00001615/*
1616 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1617 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001618int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001619{
Paul Bakker23986e52011-04-24 08:57:21 +00001620 int ret;
1621 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001622 mpi TG, TA, TB;
1623
Paul Bakker6c591fa2011-05-05 11:49:20 +00001624 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001625
Paul Bakker5121ce52009-01-03 21:22:43 +00001626 MPI_CHK( mpi_copy( &TA, A ) );
1627 MPI_CHK( mpi_copy( &TB, B ) );
1628
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001629 lz = mpi_lsb( &TA );
1630 lzt = mpi_lsb( &TB );
1631
1632 if ( lzt < lz )
1633 lz = lzt;
1634
1635 MPI_CHK( mpi_shift_r( &TA, lz ) );
1636 MPI_CHK( mpi_shift_r( &TB, lz ) );
1637
Paul Bakker5121ce52009-01-03 21:22:43 +00001638 TA.s = TB.s = 1;
1639
1640 while( mpi_cmp_int( &TA, 0 ) != 0 )
1641 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001642 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1643 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001644
1645 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1646 {
1647 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1648 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1649 }
1650 else
1651 {
1652 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1653 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1654 }
1655 }
1656
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001657 MPI_CHK( mpi_shift_l( &TB, lz ) );
1658 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001659
1660cleanup:
1661
Paul Bakker6c591fa2011-05-05 11:49:20 +00001662 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001663
1664 return( ret );
1665}
1666
Paul Bakker358d3252014-04-30 16:11:39 +02001667/*
1668 * Fill X with size bytes of random.
1669 *
1670 * Use a temporary bytes representation to make sure the result is the same
1671 * regardless of the platform endianness (usefull when f_rng is actually
1672 * deterministic, eg for tests).
1673 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001674int mpi_fill_random( mpi *X, size_t size,
1675 int (*f_rng)(void *, unsigned char *, size_t),
1676 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001677{
Paul Bakker23986e52011-04-24 08:57:21 +00001678 int ret;
Paul Bakker358d3252014-04-30 16:11:39 +02001679 unsigned char buf[POLARSSL_MPI_MAX_SIZE];
1680
1681 if( size > POLARSSL_MPI_MAX_SIZE )
1682 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001683
Paul Bakker39dfdac2012-02-12 17:17:27 +00001684 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001685 MPI_CHK( mpi_lset( X, 0 ) );
1686
Paul Bakker358d3252014-04-30 16:11:39 +02001687 MPI_CHK( f_rng( p_rng, buf, size ) );
1688 MPI_CHK( mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001689
1690cleanup:
1691 return( ret );
1692}
1693
Paul Bakker5121ce52009-01-03 21:22:43 +00001694/*
1695 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1696 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001697int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001698{
1699 int ret;
1700 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1701
1702 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001703 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001704
Paul Bakker6c591fa2011-05-05 11:49:20 +00001705 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1706 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1707 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001708
1709 MPI_CHK( mpi_gcd( &G, A, N ) );
1710
1711 if( mpi_cmp_int( &G, 1 ) != 0 )
1712 {
Paul Bakker40e46942009-01-03 21:51:57 +00001713 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001714 goto cleanup;
1715 }
1716
1717 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1718 MPI_CHK( mpi_copy( &TU, &TA ) );
1719 MPI_CHK( mpi_copy( &TB, N ) );
1720 MPI_CHK( mpi_copy( &TV, N ) );
1721
1722 MPI_CHK( mpi_lset( &U1, 1 ) );
1723 MPI_CHK( mpi_lset( &U2, 0 ) );
1724 MPI_CHK( mpi_lset( &V1, 0 ) );
1725 MPI_CHK( mpi_lset( &V2, 1 ) );
1726
1727 do
1728 {
1729 while( ( TU.p[0] & 1 ) == 0 )
1730 {
1731 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1732
1733 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1734 {
1735 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1736 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1737 }
1738
1739 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1740 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1741 }
1742
1743 while( ( TV.p[0] & 1 ) == 0 )
1744 {
1745 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1746
1747 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1748 {
1749 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1750 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1751 }
1752
1753 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1754 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1755 }
1756
1757 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1758 {
1759 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1760 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1761 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1762 }
1763 else
1764 {
1765 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1766 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1767 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1768 }
1769 }
1770 while( mpi_cmp_int( &TU, 0 ) != 0 );
1771
1772 while( mpi_cmp_int( &V1, 0 ) < 0 )
1773 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1774
1775 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1776 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1777
1778 MPI_CHK( mpi_copy( X, &V1 ) );
1779
1780cleanup:
1781
Paul Bakker6c591fa2011-05-05 11:49:20 +00001782 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1783 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1784 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001785
1786 return( ret );
1787}
1788
Paul Bakkerd9374b02012-11-02 11:02:58 +00001789#if defined(POLARSSL_GENPRIME)
1790
Paul Bakker5121ce52009-01-03 21:22:43 +00001791static const int small_prime[] =
1792{
1793 3, 5, 7, 11, 13, 17, 19, 23,
1794 29, 31, 37, 41, 43, 47, 53, 59,
1795 61, 67, 71, 73, 79, 83, 89, 97,
1796 101, 103, 107, 109, 113, 127, 131, 137,
1797 139, 149, 151, 157, 163, 167, 173, 179,
1798 181, 191, 193, 197, 199, 211, 223, 227,
1799 229, 233, 239, 241, 251, 257, 263, 269,
1800 271, 277, 281, 283, 293, 307, 311, 313,
1801 317, 331, 337, 347, 349, 353, 359, 367,
1802 373, 379, 383, 389, 397, 401, 409, 419,
1803 421, 431, 433, 439, 443, 449, 457, 461,
1804 463, 467, 479, 487, 491, 499, 503, 509,
1805 521, 523, 541, 547, 557, 563, 569, 571,
1806 577, 587, 593, 599, 601, 607, 613, 617,
1807 619, 631, 641, 643, 647, 653, 659, 661,
1808 673, 677, 683, 691, 701, 709, 719, 727,
1809 733, 739, 743, 751, 757, 761, 769, 773,
1810 787, 797, 809, 811, 821, 823, 827, 829,
1811 839, 853, 857, 859, 863, 877, 881, 883,
1812 887, 907, 911, 919, 929, 937, 941, 947,
1813 953, 967, 971, 977, 983, 991, 997, -103
1814};
1815
1816/*
1817 * Miller-Rabin primality test (HAC 4.24)
1818 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001819int mpi_is_prime( mpi *X,
1820 int (*f_rng)(void *, unsigned char *, size_t),
1821 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001822{
Paul Bakker23986e52011-04-24 08:57:21 +00001823 int ret, xs;
1824 size_t i, j, n, s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001825 mpi W, R, T, A, RR;
Paul Bakker5121ce52009-01-03 21:22:43 +00001826
Paul Bakker48eab262009-06-25 21:25:49 +00001827 if( mpi_cmp_int( X, 0 ) == 0 ||
1828 mpi_cmp_int( X, 1 ) == 0 )
1829 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1830
1831 if( mpi_cmp_int( X, 2 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001832 return( 0 );
1833
Paul Bakker6c591fa2011-05-05 11:49:20 +00001834 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
1835 mpi_init( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001836
1837 xs = X->s; X->s = 1;
1838
1839 /*
1840 * test trivial factors first
1841 */
1842 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001843 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001844
1845 for( i = 0; small_prime[i] > 0; i++ )
1846 {
Paul Bakkera755ca12011-04-24 09:11:17 +00001847 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001848
1849 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
1850 return( 0 );
1851
1852 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1853
1854 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001855 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001856 }
1857
1858 /*
1859 * W = |X| - 1
1860 * R = W >> lsb( W )
1861 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001862 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001863 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001864 MPI_CHK( mpi_copy( &R, &W ) );
1865 MPI_CHK( mpi_shift_r( &R, s ) );
1866
1867 i = mpi_msb( X );
1868 /*
1869 * HAC, table 4.4
1870 */
1871 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1872 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1873 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1874
1875 for( i = 0; i < n; i++ )
1876 {
1877 /*
1878 * pick a random A, 1 < A < |X| - 1
1879 */
Paul Bakker901c6562012-04-20 13:25:38 +00001880 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001881
Paul Bakkerb94081b2011-01-05 15:53:06 +00001882 if( mpi_cmp_mpi( &A, &W ) >= 0 )
1883 {
1884 j = mpi_msb( &A ) - mpi_msb( &W );
1885 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1886 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001887 A.p[0] |= 3;
1888
1889 /*
1890 * A = A^R mod |X|
1891 */
1892 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1893
1894 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1895 mpi_cmp_int( &A, 1 ) == 0 )
1896 continue;
1897
1898 j = 1;
1899 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1900 {
1901 /*
1902 * A = A * A mod |X|
1903 */
1904 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1905 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1906
1907 if( mpi_cmp_int( &A, 1 ) == 0 )
1908 break;
1909
1910 j++;
1911 }
1912
1913 /*
1914 * not prime if A != |X| - 1 or A == 1
1915 */
1916 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1917 mpi_cmp_int( &A, 1 ) == 0 )
1918 {
Paul Bakker40e46942009-01-03 21:51:57 +00001919 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001920 break;
1921 }
1922 }
1923
1924cleanup:
1925
1926 X->s = xs;
1927
Paul Bakker6c591fa2011-05-05 11:49:20 +00001928 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
1929 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001930
1931 return( ret );
1932}
1933
1934/*
1935 * Prime number generation
1936 */
Paul Bakker23986e52011-04-24 08:57:21 +00001937int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001938 int (*f_rng)(void *, unsigned char *, size_t),
1939 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001940{
Paul Bakker23986e52011-04-24 08:57:21 +00001941 int ret;
1942 size_t k, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001943 mpi Y;
1944
Paul Bakkerfe3256e2011-11-25 12:11:43 +00001945 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00001946 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001947
Paul Bakker6c591fa2011-05-05 11:49:20 +00001948 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001949
1950 n = BITS_TO_LIMBS( nbits );
1951
Paul Bakker901c6562012-04-20 13:25:38 +00001952 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001953
1954 k = mpi_msb( X );
1955 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
1956 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
1957
1958 X->p[0] |= 3;
1959
1960 if( dh_flag == 0 )
1961 {
1962 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
1963 {
Paul Bakker40e46942009-01-03 21:51:57 +00001964 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001965 goto cleanup;
1966
1967 MPI_CHK( mpi_add_int( X, X, 2 ) );
1968 }
1969 }
1970 else
1971 {
1972 MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
1973 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1974
1975 while( 1 )
1976 {
1977 if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
1978 {
1979 if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
1980 break;
1981
Paul Bakker40e46942009-01-03 21:51:57 +00001982 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001983 goto cleanup;
1984 }
1985
Paul Bakker40e46942009-01-03 21:51:57 +00001986 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001987 goto cleanup;
1988
1989 MPI_CHK( mpi_add_int( &Y, X, 1 ) );
1990 MPI_CHK( mpi_add_int( X, X, 2 ) );
1991 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1992 }
1993 }
1994
1995cleanup:
1996
Paul Bakker6c591fa2011-05-05 11:49:20 +00001997 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001998
1999 return( ret );
2000}
2001
2002#endif
2003
Paul Bakker40e46942009-01-03 21:51:57 +00002004#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002005
Paul Bakker23986e52011-04-24 08:57:21 +00002006#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002007
2008static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2009{
2010 { 693, 609, 21 },
2011 { 1764, 868, 28 },
2012 { 768454923, 542167814, 1 }
2013};
2014
Paul Bakker5121ce52009-01-03 21:22:43 +00002015/*
2016 * Checkup routine
2017 */
2018int mpi_self_test( int verbose )
2019{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002020 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002021 mpi A, E, N, X, Y, U, V;
2022
Paul Bakker6c591fa2011-05-05 11:49:20 +00002023 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2024 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002025
2026 MPI_CHK( mpi_read_string( &A, 16,
2027 "EFE021C2645FD1DC586E69184AF4A31E" \
2028 "D5F53E93B5F123FA41680867BA110131" \
2029 "944FE7952E2517337780CB0DB80E61AA" \
2030 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2031
2032 MPI_CHK( mpi_read_string( &E, 16,
2033 "B2E7EFD37075B9F03FF989C7C5051C20" \
2034 "34D2A323810251127E7BF8625A4F49A5" \
2035 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2036 "5B5C25763222FEFCCFC38B832366C29E" ) );
2037
2038 MPI_CHK( mpi_read_string( &N, 16,
2039 "0066A198186C18C10B2F5ED9B522752A" \
2040 "9830B69916E535C8F047518A889A43A5" \
2041 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2042
2043 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2044
2045 MPI_CHK( mpi_read_string( &U, 16,
2046 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2047 "9E857EA95A03512E2BAE7391688D264A" \
2048 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2049 "8001B72E848A38CAE1C65F78E56ABDEF" \
2050 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2051 "ECF677152EF804370C1A305CAF3B5BF1" \
2052 "30879B56C61DE584A0F53A2447A51E" ) );
2053
2054 if( verbose != 0 )
2055 printf( " MPI test #1 (mul_mpi): " );
2056
2057 if( mpi_cmp_mpi( &X, &U ) != 0 )
2058 {
2059 if( verbose != 0 )
2060 printf( "failed\n" );
2061
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002062 ret = 1;
2063 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002064 }
2065
2066 if( verbose != 0 )
2067 printf( "passed\n" );
2068
2069 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2070
2071 MPI_CHK( mpi_read_string( &U, 16,
2072 "256567336059E52CAE22925474705F39A94" ) );
2073
2074 MPI_CHK( mpi_read_string( &V, 16,
2075 "6613F26162223DF488E9CD48CC132C7A" \
2076 "0AC93C701B001B092E4E5B9F73BCD27B" \
2077 "9EE50D0657C77F374E903CDFA4C642" ) );
2078
2079 if( verbose != 0 )
2080 printf( " MPI test #2 (div_mpi): " );
2081
2082 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2083 mpi_cmp_mpi( &Y, &V ) != 0 )
2084 {
2085 if( verbose != 0 )
2086 printf( "failed\n" );
2087
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002088 ret = 1;
2089 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002090 }
2091
2092 if( verbose != 0 )
2093 printf( "passed\n" );
2094
2095 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2096
2097 MPI_CHK( mpi_read_string( &U, 16,
2098 "36E139AEA55215609D2816998ED020BB" \
2099 "BD96C37890F65171D948E9BC7CBAA4D9" \
2100 "325D24D6A3C12710F10A09FA08AB87" ) );
2101
2102 if( verbose != 0 )
2103 printf( " MPI test #3 (exp_mod): " );
2104
2105 if( mpi_cmp_mpi( &X, &U ) != 0 )
2106 {
2107 if( verbose != 0 )
2108 printf( "failed\n" );
2109
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002110 ret = 1;
2111 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002112 }
2113
2114 if( verbose != 0 )
2115 printf( "passed\n" );
2116
Paul Bakker5690efc2011-05-26 13:16:06 +00002117#if defined(POLARSSL_GENPRIME)
Paul Bakker5121ce52009-01-03 21:22:43 +00002118 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2119
2120 MPI_CHK( mpi_read_string( &U, 16,
2121 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2122 "C3DBA76456363A10869622EAC2DD84EC" \
2123 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2124
2125 if( verbose != 0 )
2126 printf( " MPI test #4 (inv_mod): " );
2127
2128 if( mpi_cmp_mpi( &X, &U ) != 0 )
2129 {
2130 if( verbose != 0 )
2131 printf( "failed\n" );
2132
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002133 ret = 1;
2134 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002135 }
2136
2137 if( verbose != 0 )
2138 printf( "passed\n" );
Paul Bakker5690efc2011-05-26 13:16:06 +00002139#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002140
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002141 if( verbose != 0 )
2142 printf( " MPI test #5 (simple gcd): " );
2143
2144 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2145 {
2146 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002147 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002148
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002149 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002150
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002151 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2152 {
2153 if( verbose != 0 )
2154 printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002155
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002156 ret = 1;
2157 goto cleanup;
2158 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002159 }
2160
2161 if( verbose != 0 )
2162 printf( "passed\n" );
2163
Paul Bakker5121ce52009-01-03 21:22:43 +00002164cleanup:
2165
2166 if( ret != 0 && verbose != 0 )
2167 printf( "Unexpected error, return code = %08X\n", ret );
2168
Paul Bakker6c591fa2011-05-05 11:49:20 +00002169 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2170 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002171
2172 if( verbose != 0 )
2173 printf( "\n" );
2174
2175 return( ret );
2176}
2177
2178#endif
2179
2180#endif