blob: cc4b1f368ac5b69b28898b91ac2d66014d969e6f [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Paul Bakker84f12b72010-07-18 10:13:04 +00004 * Copyright (C) 2006-2010, Brainspark B.V.
Paul Bakkerb96f1542010-07-18 20:36:00 +00005 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
Paul Bakker84f12b72010-07-18 10:13:04 +00007 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
Paul Bakkerb96f1542010-07-18 20:36:00 +00008 *
Paul Bakker77b385e2009-07-28 17:23:11 +00009 * All rights reserved.
Paul Bakkere0ccd0a2009-01-04 16:27:10 +000010 *
Paul Bakker5121ce52009-01-03 21:22:43 +000011 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25/*
26 * This MPI implementation is based on:
27 *
28 * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
29 * http://www.stillhq.com/extracted/gnupg-api/mpi/
30 * http://math.libtomcrypt.com/files/tommath.pdf
31 */
32
Paul Bakker40e46942009-01-03 21:51:57 +000033#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000034
Paul Bakker40e46942009-01-03 21:51:57 +000035#if defined(POLARSSL_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000036
Paul Bakker40e46942009-01-03 21:51:57 +000037#include "polarssl/bignum.h"
38#include "polarssl/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000039
Paul Bakker6e339b52013-07-03 13:37:05 +020040#if defined(POLARSSL_MEMORY_C)
41#include "polarssl/memory.h"
42#else
43#define polarssl_malloc malloc
44#define polarssl_free free
45#endif
46
Paul Bakker5121ce52009-01-03 21:22:43 +000047#include <stdlib.h>
Paul Bakker5121ce52009-01-03 21:22:43 +000048
Paul Bakkerf9688572011-05-05 10:00:45 +000049#define ciL (sizeof(t_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000050#define biL (ciL << 3) /* bits in limb */
51#define biH (ciL << 2) /* half limb size */
52
53/*
54 * Convert between bits/chars and number of limbs
55 */
56#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL)
57#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
58
59/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000060 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000061 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000062void mpi_init( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000063{
Paul Bakker6c591fa2011-05-05 11:49:20 +000064 if( X == NULL )
65 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000066
Paul Bakker6c591fa2011-05-05 11:49:20 +000067 X->s = 1;
68 X->n = 0;
69 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000070}
71
72/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000073 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000074 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000075void mpi_free( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000076{
Paul Bakker6c591fa2011-05-05 11:49:20 +000077 if( X == NULL )
78 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000079
Paul Bakker6c591fa2011-05-05 11:49:20 +000080 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +000081 {
Paul Bakker6c591fa2011-05-05 11:49:20 +000082 memset( X->p, 0, X->n * ciL );
Paul Bakker6e339b52013-07-03 13:37:05 +020083 polarssl_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +000084 }
85
Paul Bakker6c591fa2011-05-05 11:49:20 +000086 X->s = 1;
87 X->n = 0;
88 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000089}
90
91/*
92 * Enlarge to the specified number of limbs
93 */
Paul Bakker23986e52011-04-24 08:57:21 +000094int mpi_grow( mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +000095{
Paul Bakkera755ca12011-04-24 09:11:17 +000096 t_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +000097
Paul Bakkerf9688572011-05-05 10:00:45 +000098 if( nblimbs > POLARSSL_MPI_MAX_LIMBS )
Paul Bakker69e095c2011-12-10 21:55:01 +000099 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000100
Paul Bakker5121ce52009-01-03 21:22:43 +0000101 if( X->n < nblimbs )
102 {
Paul Bakker6e339b52013-07-03 13:37:05 +0200103 if( ( p = (t_uint *) polarssl_malloc( nblimbs * ciL ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000104 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000105
106 memset( p, 0, nblimbs * ciL );
107
108 if( X->p != NULL )
109 {
110 memcpy( p, X->p, X->n * ciL );
111 memset( X->p, 0, X->n * ciL );
Paul Bakker6e339b52013-07-03 13:37:05 +0200112 polarssl_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000113 }
114
115 X->n = nblimbs;
116 X->p = p;
117 }
118
119 return( 0 );
120}
121
122/*
123 * Copy the contents of Y into X
124 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000125int mpi_copy( mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000126{
Paul Bakker23986e52011-04-24 08:57:21 +0000127 int ret;
128 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000129
130 if( X == Y )
131 return( 0 );
132
133 for( i = Y->n - 1; i > 0; i-- )
134 if( Y->p[i] != 0 )
135 break;
136 i++;
137
138 X->s = Y->s;
139
140 MPI_CHK( mpi_grow( X, i ) );
141
142 memset( X->p, 0, X->n * ciL );
143 memcpy( X->p, Y->p, i * ciL );
144
145cleanup:
146
147 return( ret );
148}
149
150/*
151 * Swap the contents of X and Y
152 */
153void mpi_swap( mpi *X, mpi *Y )
154{
155 mpi T;
156
157 memcpy( &T, X, sizeof( mpi ) );
158 memcpy( X, Y, sizeof( mpi ) );
159 memcpy( Y, &T, sizeof( mpi ) );
160}
161
162/*
163 * Set value from integer
164 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000165int mpi_lset( mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000166{
167 int ret;
168
169 MPI_CHK( mpi_grow( X, 1 ) );
170 memset( X->p, 0, X->n * ciL );
171
172 X->p[0] = ( z < 0 ) ? -z : z;
173 X->s = ( z < 0 ) ? -1 : 1;
174
175cleanup:
176
177 return( ret );
178}
179
180/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000181 * Get a specific bit
182 */
Paul Bakker6b906e52012-05-08 12:01:43 +0000183int mpi_get_bit( const mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000184{
185 if( X->n * biL <= pos )
186 return( 0 );
187
188 return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
189}
190
191/*
192 * Set a bit to a specific value of 0 or 1
193 */
194int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
195{
196 int ret = 0;
197 size_t off = pos / biL;
198 size_t idx = pos % biL;
199
200 if( val != 0 && val != 1 )
201 return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
202
203 if( X->n * biL <= pos )
204 {
205 if( val == 0 )
206 return ( 0 );
207
208 MPI_CHK( mpi_grow( X, off + 1 ) );
209 }
210
211 X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
212
213cleanup:
214
215 return( ret );
216}
217
218/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000219 * Return the number of least significant bits
220 */
Paul Bakker23986e52011-04-24 08:57:21 +0000221size_t mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000222{
Paul Bakker23986e52011-04-24 08:57:21 +0000223 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000224
225 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000226 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000227 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
228 return( count );
229
230 return( 0 );
231}
232
233/*
234 * Return the number of most significant bits
235 */
Paul Bakker23986e52011-04-24 08:57:21 +0000236size_t mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000237{
Paul Bakker23986e52011-04-24 08:57:21 +0000238 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000239
240 for( i = X->n - 1; i > 0; i-- )
241 if( X->p[i] != 0 )
242 break;
243
Paul Bakker23986e52011-04-24 08:57:21 +0000244 for( j = biL; j > 0; j-- )
245 if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000246 break;
247
Paul Bakker23986e52011-04-24 08:57:21 +0000248 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000249}
250
251/*
252 * Return the total size in bytes
253 */
Paul Bakker23986e52011-04-24 08:57:21 +0000254size_t mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000255{
256 return( ( mpi_msb( X ) + 7 ) >> 3 );
257}
258
259/*
260 * Convert an ASCII character to digit value
261 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000262static int mpi_get_digit( t_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000263{
264 *d = 255;
265
266 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
267 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
268 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
269
Paul Bakkera755ca12011-04-24 09:11:17 +0000270 if( *d >= (t_uint) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000271 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000272
273 return( 0 );
274}
275
276/*
277 * Import from an ASCII string
278 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000279int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000280{
Paul Bakker23986e52011-04-24 08:57:21 +0000281 int ret;
282 size_t i, j, slen, n;
Paul Bakkera755ca12011-04-24 09:11:17 +0000283 t_uint d;
Paul Bakker5121ce52009-01-03 21:22:43 +0000284 mpi T;
285
286 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000287 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000288
Paul Bakker6c591fa2011-05-05 11:49:20 +0000289 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000290
Paul Bakkerff60ee62010-03-16 21:09:09 +0000291 slen = strlen( s );
292
Paul Bakker5121ce52009-01-03 21:22:43 +0000293 if( radix == 16 )
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 Bakkerfc4f46f2013-06-24 19:23: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]++;
1114 mpi_sub_mpi( &X, &X, &Y );
1115 }
1116 mpi_shift_r( &Y, biL * (n - t) );
1117
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 {
Paul Bakker62261d62012-10-02 12:19:31 +00001124#if defined(POLARSSL_HAVE_UDBL)
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001125 t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001126
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001127 r = (t_udbl) X.p[i] << biL;
1128 r |= (t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001129 r /= Y.p[t];
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001130 if( r > ((t_udbl) 1 << biL) - 1)
1131 r = ((t_udbl) 1 << biL) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001132
Paul Bakkera755ca12011-04-24 09:11:17 +00001133 Z.p[i - t - 1] = (t_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001134#else
1135 /*
1136 * __udiv_qrnnd_c, from gmp/longlong.h
1137 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001138 t_uint q0, q1, r0, r1;
1139 t_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001140
1141 d = Y.p[t];
1142 d0 = ( d << biH ) >> biH;
1143 d1 = ( d >> biH );
1144
1145 q1 = X.p[i] / d1;
1146 r1 = X.p[i] - d1 * q1;
1147 r1 <<= biH;
1148 r1 |= ( X.p[i - 1] >> biH );
1149
1150 m = q1 * d0;
1151 if( r1 < m )
1152 {
1153 q1--, r1 += d;
1154 while( r1 >= d && r1 < m )
1155 q1--, r1 += d;
1156 }
1157 r1 -= m;
1158
1159 q0 = r1 / d1;
1160 r0 = r1 - d1 * q0;
1161 r0 <<= biH;
1162 r0 |= ( X.p[i - 1] << biH ) >> biH;
1163
1164 m = q0 * d0;
1165 if( r0 < m )
1166 {
1167 q0--, r0 += d;
1168 while( r0 >= d && r0 < m )
1169 q0--, r0 += d;
1170 }
1171 r0 -= m;
1172
1173 Z.p[i - t - 1] = ( q1 << biH ) | q0;
1174#endif
1175 }
1176
1177 Z.p[i - t - 1]++;
1178 do
1179 {
1180 Z.p[i - t - 1]--;
1181
1182 MPI_CHK( mpi_lset( &T1, 0 ) );
1183 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1184 T1.p[1] = Y.p[t];
1185 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1186
1187 MPI_CHK( mpi_lset( &T2, 0 ) );
1188 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1189 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1190 T2.p[2] = X.p[i];
1191 }
1192 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1193
1194 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1195 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1196 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1197
1198 if( mpi_cmp_int( &X, 0 ) < 0 )
1199 {
1200 MPI_CHK( mpi_copy( &T1, &Y ) );
1201 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1202 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1203 Z.p[i - t - 1]--;
1204 }
1205 }
1206
1207 if( Q != NULL )
1208 {
1209 mpi_copy( Q, &Z );
1210 Q->s = A->s * B->s;
1211 }
1212
1213 if( R != NULL )
1214 {
1215 mpi_shift_r( &X, k );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001216 X.s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001217 mpi_copy( R, &X );
1218
Paul Bakker5121ce52009-01-03 21:22:43 +00001219 if( mpi_cmp_int( R, 0 ) == 0 )
1220 R->s = 1;
1221 }
1222
1223cleanup:
1224
Paul Bakker6c591fa2011-05-05 11:49:20 +00001225 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1226 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001227
1228 return( ret );
1229}
1230
1231/*
1232 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001233 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001234int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001235{
1236 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001237 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001238
1239 p[0] = ( b < 0 ) ? -b : b;
1240 _B.s = ( b < 0 ) ? -1 : 1;
1241 _B.n = 1;
1242 _B.p = p;
1243
1244 return( mpi_div_mpi( Q, R, A, &_B ) );
1245}
1246
1247/*
1248 * Modulo: R = A mod B
1249 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001250int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001251{
1252 int ret;
1253
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001254 if( mpi_cmp_int( B, 0 ) < 0 )
1255 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1256
Paul Bakker5121ce52009-01-03 21:22:43 +00001257 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1258
1259 while( mpi_cmp_int( R, 0 ) < 0 )
1260 MPI_CHK( mpi_add_mpi( R, R, B ) );
1261
1262 while( mpi_cmp_mpi( R, B ) >= 0 )
1263 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1264
1265cleanup:
1266
1267 return( ret );
1268}
1269
1270/*
1271 * Modulo: r = A mod b
1272 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001273int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001274{
Paul Bakker23986e52011-04-24 08:57:21 +00001275 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001276 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001277
1278 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001279 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001280
1281 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001282 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001283
1284 /*
1285 * handle trivial cases
1286 */
1287 if( b == 1 )
1288 {
1289 *r = 0;
1290 return( 0 );
1291 }
1292
1293 if( b == 2 )
1294 {
1295 *r = A->p[0] & 1;
1296 return( 0 );
1297 }
1298
1299 /*
1300 * general case
1301 */
Paul Bakker23986e52011-04-24 08:57:21 +00001302 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001303 {
Paul Bakker23986e52011-04-24 08:57:21 +00001304 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001305 y = ( y << biH ) | ( x >> biH );
1306 z = y / b;
1307 y -= z * b;
1308
1309 x <<= biH;
1310 y = ( y << biH ) | ( x >> biH );
1311 z = y / b;
1312 y -= z * b;
1313 }
1314
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001315 /*
1316 * If A is negative, then the current y represents a negative value.
1317 * Flipping it to the positive side.
1318 */
1319 if( A->s < 0 && y != 0 )
1320 y = b - y;
1321
Paul Bakker5121ce52009-01-03 21:22:43 +00001322 *r = y;
1323
1324 return( 0 );
1325}
1326
1327/*
1328 * Fast Montgomery initialization (thanks to Tom St Denis)
1329 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001330static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001331{
Paul Bakkera755ca12011-04-24 09:11:17 +00001332 t_uint x, m0 = N->p[0];
Paul Bakker5121ce52009-01-03 21:22:43 +00001333
1334 x = m0;
1335 x += ( ( m0 + 2 ) & 4 ) << 1;
1336 x *= ( 2 - ( m0 * x ) );
1337
1338 if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
1339 if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
1340 if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
1341
1342 *mm = ~x + 1;
1343}
1344
1345/*
1346 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1347 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001348static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001349{
Paul Bakker23986e52011-04-24 08:57:21 +00001350 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001351 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001352
1353 memset( T->p, 0, T->n * ciL );
1354
1355 d = T->p;
1356 n = N->n;
1357 m = ( B->n < n ) ? B->n : n;
1358
1359 for( i = 0; i < n; i++ )
1360 {
1361 /*
1362 * T = (T + u0*B + u1*N) / 2^biL
1363 */
1364 u0 = A->p[i];
1365 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1366
1367 mpi_mul_hlp( m, B->p, d, u0 );
1368 mpi_mul_hlp( n, N->p, d, u1 );
1369
1370 *d++ = u0; d[n + 1] = 0;
1371 }
1372
1373 memcpy( A->p, d, (n + 1) * ciL );
1374
1375 if( mpi_cmp_abs( A, N ) >= 0 )
1376 mpi_sub_hlp( n, N->p, A->p );
1377 else
1378 /* prevent timing attacks */
1379 mpi_sub_hlp( n, A->p, T->p );
1380}
1381
1382/*
1383 * Montgomery reduction: A = A * R^-1 mod N
1384 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001385static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001386{
Paul Bakkera755ca12011-04-24 09:11:17 +00001387 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001388 mpi U;
1389
Paul Bakker8ddb6452013-02-27 14:56:33 +01001390 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001391 U.p = &z;
1392
1393 mpi_montmul( A, &U, N, mm, T );
1394}
1395
1396/*
1397 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1398 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001399int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001400{
Paul Bakker23986e52011-04-24 08:57:21 +00001401 int ret;
1402 size_t wbits, wsize, one = 1;
1403 size_t i, j, nblimbs;
1404 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001405 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001406 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1407 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001408
1409 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001410 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001411
Paul Bakkerf6198c12012-05-16 08:02:29 +00001412 if( mpi_cmp_int( E, 0 ) < 0 )
1413 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1414
1415 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001416 * Init temps and window size
1417 */
1418 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001419 mpi_init( &RR ); mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001420 memset( W, 0, sizeof( W ) );
1421
1422 i = mpi_msb( E );
1423
1424 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1425 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1426
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001427 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1428 wsize = POLARSSL_MPI_WINDOW_SIZE;
1429
Paul Bakker5121ce52009-01-03 21:22:43 +00001430 j = N->n + 1;
1431 MPI_CHK( mpi_grow( X, j ) );
1432 MPI_CHK( mpi_grow( &W[1], j ) );
1433 MPI_CHK( mpi_grow( &T, j * 2 ) );
1434
1435 /*
Paul Bakker50546922012-05-19 08:40:49 +00001436 * Compensate for negative A (and correct at the end)
1437 */
1438 neg = ( A->s == -1 );
1439
1440 mpi_init( &Apos );
1441 if( neg )
1442 {
1443 MPI_CHK( mpi_copy( &Apos, A ) );
1444 Apos.s = 1;
1445 A = &Apos;
1446 }
1447
1448 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001449 * If 1st call, pre-compute R^2 mod N
1450 */
1451 if( _RR == NULL || _RR->p == NULL )
1452 {
1453 MPI_CHK( mpi_lset( &RR, 1 ) );
1454 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1455 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1456
1457 if( _RR != NULL )
1458 memcpy( _RR, &RR, sizeof( mpi ) );
1459 }
1460 else
1461 memcpy( &RR, _RR, sizeof( mpi ) );
1462
1463 /*
1464 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1465 */
1466 if( mpi_cmp_mpi( A, N ) >= 0 )
1467 mpi_mod_mpi( &W[1], A, N );
1468 else mpi_copy( &W[1], A );
1469
1470 mpi_montmul( &W[1], &RR, N, mm, &T );
1471
1472 /*
1473 * X = R^2 * R^-1 mod N = R mod N
1474 */
1475 MPI_CHK( mpi_copy( X, &RR ) );
1476 mpi_montred( X, N, mm, &T );
1477
1478 if( wsize > 1 )
1479 {
1480 /*
1481 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1482 */
Paul Bakker23986e52011-04-24 08:57:21 +00001483 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001484
1485 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1486 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1487
1488 for( i = 0; i < wsize - 1; i++ )
1489 mpi_montmul( &W[j], &W[j], N, mm, &T );
1490
1491 /*
1492 * W[i] = W[i - 1] * W[1]
1493 */
Paul Bakker23986e52011-04-24 08:57:21 +00001494 for( i = j + 1; i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001495 {
1496 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1497 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1498
1499 mpi_montmul( &W[i], &W[1], N, mm, &T );
1500 }
1501 }
1502
1503 nblimbs = E->n;
1504 bufsize = 0;
1505 nbits = 0;
1506 wbits = 0;
1507 state = 0;
1508
1509 while( 1 )
1510 {
1511 if( bufsize == 0 )
1512 {
1513 if( nblimbs-- == 0 )
1514 break;
1515
Paul Bakkera755ca12011-04-24 09:11:17 +00001516 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001517 }
1518
1519 bufsize--;
1520
1521 ei = (E->p[nblimbs] >> bufsize) & 1;
1522
1523 /*
1524 * skip leading 0s
1525 */
1526 if( ei == 0 && state == 0 )
1527 continue;
1528
1529 if( ei == 0 && state == 1 )
1530 {
1531 /*
1532 * out of window, square X
1533 */
1534 mpi_montmul( X, X, N, mm, &T );
1535 continue;
1536 }
1537
1538 /*
1539 * add ei to current window
1540 */
1541 state = 2;
1542
1543 nbits++;
1544 wbits |= (ei << (wsize - nbits));
1545
1546 if( nbits == wsize )
1547 {
1548 /*
1549 * X = X^wsize R^-1 mod N
1550 */
1551 for( i = 0; i < wsize; i++ )
1552 mpi_montmul( X, X, N, mm, &T );
1553
1554 /*
1555 * X = X * W[wbits] R^-1 mod N
1556 */
1557 mpi_montmul( X, &W[wbits], N, mm, &T );
1558
1559 state--;
1560 nbits = 0;
1561 wbits = 0;
1562 }
1563 }
1564
1565 /*
1566 * process the remaining bits
1567 */
1568 for( i = 0; i < nbits; i++ )
1569 {
1570 mpi_montmul( X, X, N, mm, &T );
1571
1572 wbits <<= 1;
1573
Paul Bakker23986e52011-04-24 08:57:21 +00001574 if( (wbits & (one << wsize)) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001575 mpi_montmul( X, &W[1], N, mm, &T );
1576 }
1577
1578 /*
1579 * X = A^E * R * R^-1 mod N = A^E mod N
1580 */
1581 mpi_montred( X, N, mm, &T );
1582
Paul Bakkerf6198c12012-05-16 08:02:29 +00001583 if( neg )
1584 {
1585 X->s = -1;
1586 mpi_add_mpi( X, N, X );
1587 }
1588
Paul Bakker5121ce52009-01-03 21:22:43 +00001589cleanup:
1590
Paul Bakker23986e52011-04-24 08:57:21 +00001591 for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001592 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001593
Paul Bakkerf6198c12012-05-16 08:02:29 +00001594 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001595
1596 if( _RR == NULL )
1597 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001598
1599 return( ret );
1600}
1601
Paul Bakker5121ce52009-01-03 21:22:43 +00001602/*
1603 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1604 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001605int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001606{
Paul Bakker23986e52011-04-24 08:57:21 +00001607 int ret;
1608 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001609 mpi TG, TA, TB;
1610
Paul Bakker6c591fa2011-05-05 11:49:20 +00001611 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001612
Paul Bakker5121ce52009-01-03 21:22:43 +00001613 MPI_CHK( mpi_copy( &TA, A ) );
1614 MPI_CHK( mpi_copy( &TB, B ) );
1615
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001616 lz = mpi_lsb( &TA );
1617 lzt = mpi_lsb( &TB );
1618
1619 if ( lzt < lz )
1620 lz = lzt;
1621
1622 MPI_CHK( mpi_shift_r( &TA, lz ) );
1623 MPI_CHK( mpi_shift_r( &TB, lz ) );
1624
Paul Bakker5121ce52009-01-03 21:22:43 +00001625 TA.s = TB.s = 1;
1626
1627 while( mpi_cmp_int( &TA, 0 ) != 0 )
1628 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001629 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1630 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001631
1632 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1633 {
1634 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1635 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1636 }
1637 else
1638 {
1639 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1640 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1641 }
1642 }
1643
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001644 MPI_CHK( mpi_shift_l( &TB, lz ) );
1645 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001646
1647cleanup:
1648
Paul Bakker6c591fa2011-05-05 11:49:20 +00001649 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001650
1651 return( ret );
1652}
1653
Paul Bakkera3d195c2011-11-27 21:07:34 +00001654int mpi_fill_random( mpi *X, size_t size,
1655 int (*f_rng)(void *, unsigned char *, size_t),
1656 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001657{
Paul Bakker23986e52011-04-24 08:57:21 +00001658 int ret;
Paul Bakker287781a2011-03-26 13:18:49 +00001659
Paul Bakker39dfdac2012-02-12 17:17:27 +00001660 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001661 MPI_CHK( mpi_lset( X, 0 ) );
1662
Paul Bakker39dfdac2012-02-12 17:17:27 +00001663 MPI_CHK( f_rng( p_rng, (unsigned char *) X->p, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001664
1665cleanup:
1666 return( ret );
1667}
1668
Paul Bakker5121ce52009-01-03 21:22:43 +00001669/*
1670 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1671 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001672int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001673{
1674 int ret;
1675 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1676
1677 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001678 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001679
Paul Bakker6c591fa2011-05-05 11:49:20 +00001680 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1681 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1682 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001683
1684 MPI_CHK( mpi_gcd( &G, A, N ) );
1685
1686 if( mpi_cmp_int( &G, 1 ) != 0 )
1687 {
Paul Bakker40e46942009-01-03 21:51:57 +00001688 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001689 goto cleanup;
1690 }
1691
1692 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1693 MPI_CHK( mpi_copy( &TU, &TA ) );
1694 MPI_CHK( mpi_copy( &TB, N ) );
1695 MPI_CHK( mpi_copy( &TV, N ) );
1696
1697 MPI_CHK( mpi_lset( &U1, 1 ) );
1698 MPI_CHK( mpi_lset( &U2, 0 ) );
1699 MPI_CHK( mpi_lset( &V1, 0 ) );
1700 MPI_CHK( mpi_lset( &V2, 1 ) );
1701
1702 do
1703 {
1704 while( ( TU.p[0] & 1 ) == 0 )
1705 {
1706 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1707
1708 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1709 {
1710 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1711 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1712 }
1713
1714 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1715 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1716 }
1717
1718 while( ( TV.p[0] & 1 ) == 0 )
1719 {
1720 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1721
1722 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1723 {
1724 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1725 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1726 }
1727
1728 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1729 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1730 }
1731
1732 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1733 {
1734 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1735 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1736 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1737 }
1738 else
1739 {
1740 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1741 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1742 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1743 }
1744 }
1745 while( mpi_cmp_int( &TU, 0 ) != 0 );
1746
1747 while( mpi_cmp_int( &V1, 0 ) < 0 )
1748 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1749
1750 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1751 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1752
1753 MPI_CHK( mpi_copy( X, &V1 ) );
1754
1755cleanup:
1756
Paul Bakker6c591fa2011-05-05 11:49:20 +00001757 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1758 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1759 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001760
1761 return( ret );
1762}
1763
Paul Bakkerd9374b02012-11-02 11:02:58 +00001764#if defined(POLARSSL_GENPRIME)
1765
Paul Bakker5121ce52009-01-03 21:22:43 +00001766static const int small_prime[] =
1767{
1768 3, 5, 7, 11, 13, 17, 19, 23,
1769 29, 31, 37, 41, 43, 47, 53, 59,
1770 61, 67, 71, 73, 79, 83, 89, 97,
1771 101, 103, 107, 109, 113, 127, 131, 137,
1772 139, 149, 151, 157, 163, 167, 173, 179,
1773 181, 191, 193, 197, 199, 211, 223, 227,
1774 229, 233, 239, 241, 251, 257, 263, 269,
1775 271, 277, 281, 283, 293, 307, 311, 313,
1776 317, 331, 337, 347, 349, 353, 359, 367,
1777 373, 379, 383, 389, 397, 401, 409, 419,
1778 421, 431, 433, 439, 443, 449, 457, 461,
1779 463, 467, 479, 487, 491, 499, 503, 509,
1780 521, 523, 541, 547, 557, 563, 569, 571,
1781 577, 587, 593, 599, 601, 607, 613, 617,
1782 619, 631, 641, 643, 647, 653, 659, 661,
1783 673, 677, 683, 691, 701, 709, 719, 727,
1784 733, 739, 743, 751, 757, 761, 769, 773,
1785 787, 797, 809, 811, 821, 823, 827, 829,
1786 839, 853, 857, 859, 863, 877, 881, 883,
1787 887, 907, 911, 919, 929, 937, 941, 947,
1788 953, 967, 971, 977, 983, 991, 997, -103
1789};
1790
1791/*
1792 * Miller-Rabin primality test (HAC 4.24)
1793 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001794int mpi_is_prime( mpi *X,
1795 int (*f_rng)(void *, unsigned char *, size_t),
1796 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001797{
Paul Bakker23986e52011-04-24 08:57:21 +00001798 int ret, xs;
1799 size_t i, j, n, s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001800 mpi W, R, T, A, RR;
Paul Bakker5121ce52009-01-03 21:22:43 +00001801
Paul Bakker48eab262009-06-25 21:25:49 +00001802 if( mpi_cmp_int( X, 0 ) == 0 ||
1803 mpi_cmp_int( X, 1 ) == 0 )
1804 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1805
1806 if( mpi_cmp_int( X, 2 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001807 return( 0 );
1808
Paul Bakker6c591fa2011-05-05 11:49:20 +00001809 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
1810 mpi_init( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001811
1812 xs = X->s; X->s = 1;
1813
1814 /*
1815 * test trivial factors first
1816 */
1817 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001818 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001819
1820 for( i = 0; small_prime[i] > 0; i++ )
1821 {
Paul Bakkera755ca12011-04-24 09:11:17 +00001822 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001823
1824 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
1825 return( 0 );
1826
1827 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1828
1829 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001830 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001831 }
1832
1833 /*
1834 * W = |X| - 1
1835 * R = W >> lsb( W )
1836 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001837 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001838 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001839 MPI_CHK( mpi_copy( &R, &W ) );
1840 MPI_CHK( mpi_shift_r( &R, s ) );
1841
1842 i = mpi_msb( X );
1843 /*
1844 * HAC, table 4.4
1845 */
1846 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1847 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1848 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1849
1850 for( i = 0; i < n; i++ )
1851 {
1852 /*
1853 * pick a random A, 1 < A < |X| - 1
1854 */
Paul Bakker901c6562012-04-20 13:25:38 +00001855 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001856
Paul Bakkerb94081b2011-01-05 15:53:06 +00001857 if( mpi_cmp_mpi( &A, &W ) >= 0 )
1858 {
1859 j = mpi_msb( &A ) - mpi_msb( &W );
1860 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1861 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001862 A.p[0] |= 3;
1863
1864 /*
1865 * A = A^R mod |X|
1866 */
1867 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1868
1869 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1870 mpi_cmp_int( &A, 1 ) == 0 )
1871 continue;
1872
1873 j = 1;
1874 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1875 {
1876 /*
1877 * A = A * A mod |X|
1878 */
1879 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1880 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1881
1882 if( mpi_cmp_int( &A, 1 ) == 0 )
1883 break;
1884
1885 j++;
1886 }
1887
1888 /*
1889 * not prime if A != |X| - 1 or A == 1
1890 */
1891 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1892 mpi_cmp_int( &A, 1 ) == 0 )
1893 {
Paul Bakker40e46942009-01-03 21:51:57 +00001894 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001895 break;
1896 }
1897 }
1898
1899cleanup:
1900
1901 X->s = xs;
1902
Paul Bakker6c591fa2011-05-05 11:49:20 +00001903 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
1904 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001905
1906 return( ret );
1907}
1908
1909/*
1910 * Prime number generation
1911 */
Paul Bakker23986e52011-04-24 08:57:21 +00001912int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001913 int (*f_rng)(void *, unsigned char *, size_t),
1914 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001915{
Paul Bakker23986e52011-04-24 08:57:21 +00001916 int ret;
1917 size_t k, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001918 mpi Y;
1919
Paul Bakkerfe3256e2011-11-25 12:11:43 +00001920 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00001921 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001922
Paul Bakker6c591fa2011-05-05 11:49:20 +00001923 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001924
1925 n = BITS_TO_LIMBS( nbits );
1926
Paul Bakker901c6562012-04-20 13:25:38 +00001927 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001928
1929 k = mpi_msb( X );
1930 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
1931 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
1932
1933 X->p[0] |= 3;
1934
1935 if( dh_flag == 0 )
1936 {
1937 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
1938 {
Paul Bakker40e46942009-01-03 21:51:57 +00001939 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001940 goto cleanup;
1941
1942 MPI_CHK( mpi_add_int( X, X, 2 ) );
1943 }
1944 }
1945 else
1946 {
1947 MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
1948 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1949
1950 while( 1 )
1951 {
1952 if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
1953 {
1954 if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
1955 break;
1956
Paul Bakker40e46942009-01-03 21:51:57 +00001957 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001958 goto cleanup;
1959 }
1960
Paul Bakker40e46942009-01-03 21:51:57 +00001961 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001962 goto cleanup;
1963
1964 MPI_CHK( mpi_add_int( &Y, X, 1 ) );
1965 MPI_CHK( mpi_add_int( X, X, 2 ) );
1966 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1967 }
1968 }
1969
1970cleanup:
1971
Paul Bakker6c591fa2011-05-05 11:49:20 +00001972 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001973
1974 return( ret );
1975}
1976
1977#endif
1978
Paul Bakker40e46942009-01-03 21:51:57 +00001979#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00001980
Paul Bakker23986e52011-04-24 08:57:21 +00001981#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001982
1983static const int gcd_pairs[GCD_PAIR_COUNT][3] =
1984{
1985 { 693, 609, 21 },
1986 { 1764, 868, 28 },
1987 { 768454923, 542167814, 1 }
1988};
1989
Paul Bakker5121ce52009-01-03 21:22:43 +00001990/*
1991 * Checkup routine
1992 */
1993int mpi_self_test( int verbose )
1994{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001995 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001996 mpi A, E, N, X, Y, U, V;
1997
Paul Bakker6c591fa2011-05-05 11:49:20 +00001998 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
1999 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002000
2001 MPI_CHK( mpi_read_string( &A, 16,
2002 "EFE021C2645FD1DC586E69184AF4A31E" \
2003 "D5F53E93B5F123FA41680867BA110131" \
2004 "944FE7952E2517337780CB0DB80E61AA" \
2005 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2006
2007 MPI_CHK( mpi_read_string( &E, 16,
2008 "B2E7EFD37075B9F03FF989C7C5051C20" \
2009 "34D2A323810251127E7BF8625A4F49A5" \
2010 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2011 "5B5C25763222FEFCCFC38B832366C29E" ) );
2012
2013 MPI_CHK( mpi_read_string( &N, 16,
2014 "0066A198186C18C10B2F5ED9B522752A" \
2015 "9830B69916E535C8F047518A889A43A5" \
2016 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2017
2018 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2019
2020 MPI_CHK( mpi_read_string( &U, 16,
2021 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2022 "9E857EA95A03512E2BAE7391688D264A" \
2023 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2024 "8001B72E848A38CAE1C65F78E56ABDEF" \
2025 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2026 "ECF677152EF804370C1A305CAF3B5BF1" \
2027 "30879B56C61DE584A0F53A2447A51E" ) );
2028
2029 if( verbose != 0 )
2030 printf( " MPI test #1 (mul_mpi): " );
2031
2032 if( mpi_cmp_mpi( &X, &U ) != 0 )
2033 {
2034 if( verbose != 0 )
2035 printf( "failed\n" );
2036
2037 return( 1 );
2038 }
2039
2040 if( verbose != 0 )
2041 printf( "passed\n" );
2042
2043 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2044
2045 MPI_CHK( mpi_read_string( &U, 16,
2046 "256567336059E52CAE22925474705F39A94" ) );
2047
2048 MPI_CHK( mpi_read_string( &V, 16,
2049 "6613F26162223DF488E9CD48CC132C7A" \
2050 "0AC93C701B001B092E4E5B9F73BCD27B" \
2051 "9EE50D0657C77F374E903CDFA4C642" ) );
2052
2053 if( verbose != 0 )
2054 printf( " MPI test #2 (div_mpi): " );
2055
2056 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2057 mpi_cmp_mpi( &Y, &V ) != 0 )
2058 {
2059 if( verbose != 0 )
2060 printf( "failed\n" );
2061
2062 return( 1 );
2063 }
2064
2065 if( verbose != 0 )
2066 printf( "passed\n" );
2067
2068 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2069
2070 MPI_CHK( mpi_read_string( &U, 16,
2071 "36E139AEA55215609D2816998ED020BB" \
2072 "BD96C37890F65171D948E9BC7CBAA4D9" \
2073 "325D24D6A3C12710F10A09FA08AB87" ) );
2074
2075 if( verbose != 0 )
2076 printf( " MPI test #3 (exp_mod): " );
2077
2078 if( mpi_cmp_mpi( &X, &U ) != 0 )
2079 {
2080 if( verbose != 0 )
2081 printf( "failed\n" );
2082
2083 return( 1 );
2084 }
2085
2086 if( verbose != 0 )
2087 printf( "passed\n" );
2088
Paul Bakker5690efc2011-05-26 13:16:06 +00002089#if defined(POLARSSL_GENPRIME)
Paul Bakker5121ce52009-01-03 21:22:43 +00002090 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2091
2092 MPI_CHK( mpi_read_string( &U, 16,
2093 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2094 "C3DBA76456363A10869622EAC2DD84EC" \
2095 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2096
2097 if( verbose != 0 )
2098 printf( " MPI test #4 (inv_mod): " );
2099
2100 if( mpi_cmp_mpi( &X, &U ) != 0 )
2101 {
2102 if( verbose != 0 )
2103 printf( "failed\n" );
2104
2105 return( 1 );
2106 }
2107
2108 if( verbose != 0 )
2109 printf( "passed\n" );
Paul Bakker5690efc2011-05-26 13:16:06 +00002110#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002111
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002112 if( verbose != 0 )
2113 printf( " MPI test #5 (simple gcd): " );
2114
2115 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2116 {
2117 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002118 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002119
Paul Bakker23986e52011-04-24 08:57:21 +00002120 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002121
Paul Bakker23986e52011-04-24 08:57:21 +00002122 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2123 {
2124 if( verbose != 0 )
2125 printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002126
Paul Bakker23986e52011-04-24 08:57:21 +00002127 return( 1 );
2128 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002129 }
2130
2131 if( verbose != 0 )
2132 printf( "passed\n" );
2133
Paul Bakker5121ce52009-01-03 21:22:43 +00002134cleanup:
2135
2136 if( ret != 0 && verbose != 0 )
2137 printf( "Unexpected error, return code = %08X\n", ret );
2138
Paul Bakker6c591fa2011-05-05 11:49:20 +00002139 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2140 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002141
2142 if( verbose != 0 )
2143 printf( "\n" );
2144
2145 return( ret );
2146}
2147
2148#endif
2149
2150#endif