blob: 4de2e9a3edf71826c6b4b2237c55b221e0ec7cb2 [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
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200133 if( Y->p == NULL )
134 {
135 mpi_free( X );
136 return( 0 );
137 }
138
Paul Bakker5121ce52009-01-03 21:22:43 +0000139 for( i = Y->n - 1; i > 0; i-- )
140 if( Y->p[i] != 0 )
141 break;
142 i++;
143
144 X->s = Y->s;
145
146 MPI_CHK( mpi_grow( X, i ) );
147
148 memset( X->p, 0, X->n * ciL );
149 memcpy( X->p, Y->p, i * ciL );
150
151cleanup:
152
153 return( ret );
154}
155
156/*
157 * Swap the contents of X and Y
158 */
159void mpi_swap( mpi *X, mpi *Y )
160{
161 mpi T;
162
163 memcpy( &T, X, sizeof( mpi ) );
164 memcpy( X, Y, sizeof( mpi ) );
165 memcpy( Y, &T, sizeof( mpi ) );
166}
167
168/*
169 * Set value from integer
170 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000171int mpi_lset( mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000172{
173 int ret;
174
175 MPI_CHK( mpi_grow( X, 1 ) );
176 memset( X->p, 0, X->n * ciL );
177
178 X->p[0] = ( z < 0 ) ? -z : z;
179 X->s = ( z < 0 ) ? -1 : 1;
180
181cleanup:
182
183 return( ret );
184}
185
186/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000187 * Get a specific bit
188 */
Paul Bakker6b906e52012-05-08 12:01:43 +0000189int mpi_get_bit( const mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000190{
191 if( X->n * biL <= pos )
192 return( 0 );
193
194 return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
195}
196
197/*
198 * Set a bit to a specific value of 0 or 1
199 */
200int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
201{
202 int ret = 0;
203 size_t off = pos / biL;
204 size_t idx = pos % biL;
205
206 if( val != 0 && val != 1 )
207 return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
208
209 if( X->n * biL <= pos )
210 {
211 if( val == 0 )
212 return ( 0 );
213
214 MPI_CHK( mpi_grow( X, off + 1 ) );
215 }
216
217 X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
218
219cleanup:
220
221 return( ret );
222}
223
224/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000225 * Return the number of least significant bits
226 */
Paul Bakker23986e52011-04-24 08:57:21 +0000227size_t mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000228{
Paul Bakker23986e52011-04-24 08:57:21 +0000229 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000230
231 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000232 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000233 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
234 return( count );
235
236 return( 0 );
237}
238
239/*
240 * Return the number of most significant bits
241 */
Paul Bakker23986e52011-04-24 08:57:21 +0000242size_t mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000243{
Paul Bakker23986e52011-04-24 08:57:21 +0000244 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000245
246 for( i = X->n - 1; i > 0; i-- )
247 if( X->p[i] != 0 )
248 break;
249
Paul Bakker23986e52011-04-24 08:57:21 +0000250 for( j = biL; j > 0; j-- )
251 if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000252 break;
253
Paul Bakker23986e52011-04-24 08:57:21 +0000254 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000255}
256
257/*
258 * Return the total size in bytes
259 */
Paul Bakker23986e52011-04-24 08:57:21 +0000260size_t mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000261{
262 return( ( mpi_msb( X ) + 7 ) >> 3 );
263}
264
265/*
266 * Convert an ASCII character to digit value
267 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000268static int mpi_get_digit( t_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000269{
270 *d = 255;
271
272 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
273 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
274 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
275
Paul Bakkera755ca12011-04-24 09:11:17 +0000276 if( *d >= (t_uint) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000277 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000278
279 return( 0 );
280}
281
282/*
283 * Import from an ASCII string
284 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000285int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000286{
Paul Bakker23986e52011-04-24 08:57:21 +0000287 int ret;
288 size_t i, j, slen, n;
Paul Bakkera755ca12011-04-24 09:11:17 +0000289 t_uint d;
Paul Bakker5121ce52009-01-03 21:22:43 +0000290 mpi T;
291
292 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000293 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000294
Paul Bakker6c591fa2011-05-05 11:49:20 +0000295 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000296
Paul Bakkerff60ee62010-03-16 21:09:09 +0000297 slen = strlen( s );
298
Paul Bakker5121ce52009-01-03 21:22:43 +0000299 if( radix == 16 )
300 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000301 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000302
303 MPI_CHK( mpi_grow( X, n ) );
304 MPI_CHK( mpi_lset( X, 0 ) );
305
Paul Bakker23986e52011-04-24 08:57:21 +0000306 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000307 {
Paul Bakker23986e52011-04-24 08:57:21 +0000308 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000309 {
310 X->s = -1;
311 break;
312 }
313
Paul Bakker23986e52011-04-24 08:57:21 +0000314 MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000315 X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
316 }
317 }
318 else
319 {
320 MPI_CHK( mpi_lset( X, 0 ) );
321
Paul Bakkerff60ee62010-03-16 21:09:09 +0000322 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000323 {
324 if( i == 0 && s[i] == '-' )
325 {
326 X->s = -1;
327 continue;
328 }
329
330 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
331 MPI_CHK( mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000332
333 if( X->s == 1 )
334 {
335 MPI_CHK( mpi_add_int( X, &T, d ) );
336 }
337 else
338 {
339 MPI_CHK( mpi_sub_int( X, &T, d ) );
340 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000341 }
342 }
343
344cleanup:
345
Paul Bakker6c591fa2011-05-05 11:49:20 +0000346 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000347
348 return( ret );
349}
350
351/*
352 * Helper to write the digits high-order first
353 */
354static int mpi_write_hlp( mpi *X, int radix, char **p )
355{
356 int ret;
Paul Bakkera755ca12011-04-24 09:11:17 +0000357 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000358
359 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000360 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000361
362 MPI_CHK( mpi_mod_int( &r, X, radix ) );
363 MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
364
365 if( mpi_cmp_int( X, 0 ) != 0 )
366 MPI_CHK( mpi_write_hlp( X, radix, p ) );
367
368 if( r < 10 )
369 *(*p)++ = (char)( r + 0x30 );
370 else
371 *(*p)++ = (char)( r + 0x37 );
372
373cleanup:
374
375 return( ret );
376}
377
378/*
379 * Export into an ASCII string
380 */
Paul Bakker23986e52011-04-24 08:57:21 +0000381int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000382{
Paul Bakker23986e52011-04-24 08:57:21 +0000383 int ret = 0;
384 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000385 char *p;
386 mpi T;
387
388 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000389 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000390
391 n = mpi_msb( X );
392 if( radix >= 4 ) n >>= 1;
393 if( radix >= 16 ) n >>= 1;
394 n += 3;
395
396 if( *slen < n )
397 {
398 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000399 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000400 }
401
402 p = s;
Paul Bakker6c591fa2011-05-05 11:49:20 +0000403 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000404
405 if( X->s == -1 )
406 *p++ = '-';
407
408 if( radix == 16 )
409 {
Paul Bakker23986e52011-04-24 08:57:21 +0000410 int c;
411 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000412
Paul Bakker23986e52011-04-24 08:57:21 +0000413 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000414 {
Paul Bakker23986e52011-04-24 08:57:21 +0000415 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000416 {
Paul Bakker23986e52011-04-24 08:57:21 +0000417 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000418
Paul Bakker23986e52011-04-24 08:57:21 +0000419 if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000420 continue;
421
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000422 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000423 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000424 k = 1;
425 }
426 }
427 }
428 else
429 {
430 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000431
432 if( T.s == -1 )
433 T.s = 1;
434
Paul Bakker5121ce52009-01-03 21:22:43 +0000435 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
436 }
437
438 *p++ = '\0';
439 *slen = p - s;
440
441cleanup:
442
Paul Bakker6c591fa2011-05-05 11:49:20 +0000443 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000444
445 return( ret );
446}
447
Paul Bakker335db3f2011-04-25 15:28:35 +0000448#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000449/*
450 * Read X from an opened file
451 */
452int mpi_read_file( mpi *X, int radix, FILE *fin )
453{
Paul Bakkera755ca12011-04-24 09:11:17 +0000454 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000455 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000456 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000457 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000458 * Buffer should have space for (short) label and decimal formatted MPI,
459 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000460 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000461 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000462
463 memset( s, 0, sizeof( s ) );
464 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000465 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000466
467 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000468 if( slen == sizeof( s ) - 2 )
469 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
470
Paul Bakker5121ce52009-01-03 21:22:43 +0000471 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
472 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
473
474 p = s + slen;
475 while( --p >= s )
476 if( mpi_get_digit( &d, radix, *p ) != 0 )
477 break;
478
479 return( mpi_read_string( X, radix, p + 1 ) );
480}
481
482/*
483 * Write X into an opened file (or stdout if fout == NULL)
484 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000485int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000486{
Paul Bakker23986e52011-04-24 08:57:21 +0000487 int ret;
488 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000489 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000490 * Buffer should have space for (short) label and decimal formatted MPI,
491 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000492 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000493 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000494
495 n = sizeof( s );
496 memset( s, 0, n );
497 n -= 2;
498
Paul Bakker23986e52011-04-24 08:57:21 +0000499 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000500
501 if( p == NULL ) p = "";
502
503 plen = strlen( p );
504 slen = strlen( s );
505 s[slen++] = '\r';
506 s[slen++] = '\n';
507
508 if( fout != NULL )
509 {
510 if( fwrite( p, 1, plen, fout ) != plen ||
511 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000512 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000513 }
514 else
515 printf( "%s%s", p, s );
516
517cleanup:
518
519 return( ret );
520}
Paul Bakker335db3f2011-04-25 15:28:35 +0000521#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000522
523/*
524 * Import X from unsigned binary data, big endian
525 */
Paul Bakker23986e52011-04-24 08:57:21 +0000526int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000527{
Paul Bakker23986e52011-04-24 08:57:21 +0000528 int ret;
529 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000530
531 for( n = 0; n < buflen; n++ )
532 if( buf[n] != 0 )
533 break;
534
535 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
536 MPI_CHK( mpi_lset( X, 0 ) );
537
Paul Bakker23986e52011-04-24 08:57:21 +0000538 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000539 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000540
541cleanup:
542
543 return( ret );
544}
545
546/*
547 * Export X into unsigned binary data, big endian
548 */
Paul Bakker23986e52011-04-24 08:57:21 +0000549int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000550{
Paul Bakker23986e52011-04-24 08:57:21 +0000551 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000552
553 n = mpi_size( X );
554
555 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000556 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000557
558 memset( buf, 0, buflen );
559
560 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
561 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
562
563 return( 0 );
564}
565
566/*
567 * Left-shift: X <<= count
568 */
Paul Bakker23986e52011-04-24 08:57:21 +0000569int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000570{
Paul Bakker23986e52011-04-24 08:57:21 +0000571 int ret;
572 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000573 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000574
575 v0 = count / (biL );
576 t1 = count & (biL - 1);
577
578 i = mpi_msb( X ) + count;
579
Paul Bakkerf9688572011-05-05 10:00:45 +0000580 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000581 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
582
583 ret = 0;
584
585 /*
586 * shift by count / limb_size
587 */
588 if( v0 > 0 )
589 {
Paul Bakker23986e52011-04-24 08:57:21 +0000590 for( i = X->n; i > v0; i-- )
591 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000592
Paul Bakker23986e52011-04-24 08:57:21 +0000593 for( ; i > 0; i-- )
594 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000595 }
596
597 /*
598 * shift by count % limb_size
599 */
600 if( t1 > 0 )
601 {
602 for( i = v0; i < X->n; i++ )
603 {
604 r1 = X->p[i] >> (biL - t1);
605 X->p[i] <<= t1;
606 X->p[i] |= r0;
607 r0 = r1;
608 }
609 }
610
611cleanup:
612
613 return( ret );
614}
615
616/*
617 * Right-shift: X >>= count
618 */
Paul Bakker23986e52011-04-24 08:57:21 +0000619int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000620{
Paul Bakker23986e52011-04-24 08:57:21 +0000621 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000622 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000623
624 v0 = count / biL;
625 v1 = count & (biL - 1);
626
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100627 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
628 return mpi_lset( X, 0 );
629
Paul Bakker5121ce52009-01-03 21:22:43 +0000630 /*
631 * shift by count / limb_size
632 */
633 if( v0 > 0 )
634 {
635 for( i = 0; i < X->n - v0; i++ )
636 X->p[i] = X->p[i + v0];
637
638 for( ; i < X->n; i++ )
639 X->p[i] = 0;
640 }
641
642 /*
643 * shift by count % limb_size
644 */
645 if( v1 > 0 )
646 {
Paul Bakker23986e52011-04-24 08:57:21 +0000647 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000648 {
Paul Bakker23986e52011-04-24 08:57:21 +0000649 r1 = X->p[i - 1] << (biL - v1);
650 X->p[i - 1] >>= v1;
651 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000652 r0 = r1;
653 }
654 }
655
656 return( 0 );
657}
658
659/*
660 * Compare unsigned values
661 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000662int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000663{
Paul Bakker23986e52011-04-24 08:57:21 +0000664 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000665
Paul Bakker23986e52011-04-24 08:57:21 +0000666 for( i = X->n; i > 0; i-- )
667 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000668 break;
669
Paul Bakker23986e52011-04-24 08:57:21 +0000670 for( j = Y->n; j > 0; j-- )
671 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000672 break;
673
Paul Bakker23986e52011-04-24 08:57:21 +0000674 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000675 return( 0 );
676
677 if( i > j ) return( 1 );
678 if( j > i ) return( -1 );
679
Paul Bakker23986e52011-04-24 08:57:21 +0000680 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000681 {
Paul Bakker23986e52011-04-24 08:57:21 +0000682 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
683 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000684 }
685
686 return( 0 );
687}
688
689/*
690 * Compare signed values
691 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000692int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000693{
Paul Bakker23986e52011-04-24 08:57:21 +0000694 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000695
Paul Bakker23986e52011-04-24 08:57:21 +0000696 for( i = X->n; i > 0; i-- )
697 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000698 break;
699
Paul Bakker23986e52011-04-24 08:57:21 +0000700 for( j = Y->n; j > 0; j-- )
701 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000702 break;
703
Paul Bakker23986e52011-04-24 08:57:21 +0000704 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000705 return( 0 );
706
707 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000708 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000709
710 if( X->s > 0 && Y->s < 0 ) return( 1 );
711 if( Y->s > 0 && X->s < 0 ) return( -1 );
712
Paul Bakker23986e52011-04-24 08:57:21 +0000713 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000714 {
Paul Bakker23986e52011-04-24 08:57:21 +0000715 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
716 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000717 }
718
719 return( 0 );
720}
721
722/*
723 * Compare signed values
724 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000725int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000726{
727 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000728 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000729
730 *p = ( z < 0 ) ? -z : z;
731 Y.s = ( z < 0 ) ? -1 : 1;
732 Y.n = 1;
733 Y.p = p;
734
735 return( mpi_cmp_mpi( X, &Y ) );
736}
737
738/*
739 * Unsigned addition: X = |A| + |B| (HAC 14.7)
740 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000741int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000742{
Paul Bakker23986e52011-04-24 08:57:21 +0000743 int ret;
744 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000745 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000746
747 if( X == B )
748 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000749 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000750 }
751
752 if( X != A )
753 MPI_CHK( mpi_copy( X, A ) );
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000754
755 /*
756 * X should always be positive as a result of unsigned additions.
757 */
758 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000759
Paul Bakker23986e52011-04-24 08:57:21 +0000760 for( j = B->n; j > 0; j-- )
761 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000762 break;
763
Paul Bakker23986e52011-04-24 08:57:21 +0000764 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000765
766 o = B->p; p = X->p; c = 0;
767
Paul Bakker23986e52011-04-24 08:57:21 +0000768 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000769 {
770 *p += c; c = ( *p < c );
771 *p += *o; c += ( *p < *o );
772 }
773
774 while( c != 0 )
775 {
776 if( i >= X->n )
777 {
778 MPI_CHK( mpi_grow( X, i + 1 ) );
779 p = X->p + i;
780 }
781
Paul Bakker2d319fd2012-09-16 21:34:26 +0000782 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000783 }
784
785cleanup:
786
787 return( ret );
788}
789
790/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100791 * Helper for mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000792 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000793static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000794{
Paul Bakker23986e52011-04-24 08:57:21 +0000795 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000796 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000797
798 for( i = c = 0; i < n; i++, s++, d++ )
799 {
800 z = ( *d < c ); *d -= c;
801 c = ( *d < *s ) + z; *d -= *s;
802 }
803
804 while( c != 0 )
805 {
806 z = ( *d < c ); *d -= c;
807 c = z; i++; d++;
808 }
809}
810
811/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100812 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000813 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000814int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000815{
816 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000817 int ret;
818 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000819
820 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000821 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000822
Paul Bakker6c591fa2011-05-05 11:49:20 +0000823 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000824
825 if( X == B )
826 {
827 MPI_CHK( mpi_copy( &TB, B ) );
828 B = &TB;
829 }
830
831 if( X != A )
832 MPI_CHK( mpi_copy( X, A ) );
833
Paul Bakker1ef7a532009-06-20 10:50:55 +0000834 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100835 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000836 */
837 X->s = 1;
838
Paul Bakker5121ce52009-01-03 21:22:43 +0000839 ret = 0;
840
Paul Bakker23986e52011-04-24 08:57:21 +0000841 for( n = B->n; n > 0; n-- )
842 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000843 break;
844
Paul Bakker23986e52011-04-24 08:57:21 +0000845 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000846
847cleanup:
848
Paul Bakker6c591fa2011-05-05 11:49:20 +0000849 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000850
851 return( ret );
852}
853
854/*
855 * Signed addition: X = A + B
856 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000857int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000858{
859 int ret, s = A->s;
860
861 if( A->s * B->s < 0 )
862 {
863 if( mpi_cmp_abs( A, B ) >= 0 )
864 {
865 MPI_CHK( mpi_sub_abs( X, A, B ) );
866 X->s = s;
867 }
868 else
869 {
870 MPI_CHK( mpi_sub_abs( X, B, A ) );
871 X->s = -s;
872 }
873 }
874 else
875 {
876 MPI_CHK( mpi_add_abs( X, A, B ) );
877 X->s = s;
878 }
879
880cleanup:
881
882 return( ret );
883}
884
885/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100886 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +0000887 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000888int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000889{
890 int ret, s = A->s;
891
892 if( A->s * B->s > 0 )
893 {
894 if( mpi_cmp_abs( A, B ) >= 0 )
895 {
896 MPI_CHK( mpi_sub_abs( X, A, B ) );
897 X->s = s;
898 }
899 else
900 {
901 MPI_CHK( mpi_sub_abs( X, B, A ) );
902 X->s = -s;
903 }
904 }
905 else
906 {
907 MPI_CHK( mpi_add_abs( X, A, B ) );
908 X->s = s;
909 }
910
911cleanup:
912
913 return( ret );
914}
915
916/*
917 * Signed addition: X = A + b
918 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000919int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000920{
921 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000922 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000923
924 p[0] = ( b < 0 ) ? -b : b;
925 _B.s = ( b < 0 ) ? -1 : 1;
926 _B.n = 1;
927 _B.p = p;
928
929 return( mpi_add_mpi( X, A, &_B ) );
930}
931
932/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100933 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +0000934 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000935int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000936{
937 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000938 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000939
940 p[0] = ( b < 0 ) ? -b : b;
941 _B.s = ( b < 0 ) ? -1 : 1;
942 _B.n = 1;
943 _B.p = p;
944
945 return( mpi_sub_mpi( X, A, &_B ) );
946}
947
948/*
949 * Helper for mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +0200950 */
951static
952#if defined(__APPLE__) && defined(__arm__)
953/*
954 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
955 * appears to need this to prevent bad ARM code generation at -O3.
956 */
957__attribute__ ((noinline))
958#endif
959void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000960{
Paul Bakkera755ca12011-04-24 09:11:17 +0000961 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000962
963#if defined(MULADDC_HUIT)
964 for( ; i >= 8; i -= 8 )
965 {
966 MULADDC_INIT
967 MULADDC_HUIT
968 MULADDC_STOP
969 }
970
971 for( ; i > 0; i-- )
972 {
973 MULADDC_INIT
974 MULADDC_CORE
975 MULADDC_STOP
976 }
977#else
978 for( ; i >= 16; i -= 16 )
979 {
980 MULADDC_INIT
981 MULADDC_CORE MULADDC_CORE
982 MULADDC_CORE MULADDC_CORE
983 MULADDC_CORE MULADDC_CORE
984 MULADDC_CORE MULADDC_CORE
985
986 MULADDC_CORE MULADDC_CORE
987 MULADDC_CORE MULADDC_CORE
988 MULADDC_CORE MULADDC_CORE
989 MULADDC_CORE MULADDC_CORE
990 MULADDC_STOP
991 }
992
993 for( ; i >= 8; i -= 8 )
994 {
995 MULADDC_INIT
996 MULADDC_CORE MULADDC_CORE
997 MULADDC_CORE MULADDC_CORE
998
999 MULADDC_CORE MULADDC_CORE
1000 MULADDC_CORE MULADDC_CORE
1001 MULADDC_STOP
1002 }
1003
1004 for( ; i > 0; i-- )
1005 {
1006 MULADDC_INIT
1007 MULADDC_CORE
1008 MULADDC_STOP
1009 }
1010#endif
1011
1012 t++;
1013
1014 do {
1015 *d += c; c = ( *d < c ); d++;
1016 }
1017 while( c != 0 );
1018}
1019
1020/*
1021 * Baseline multiplication: X = A * B (HAC 14.12)
1022 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001023int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001024{
Paul Bakker23986e52011-04-24 08:57:21 +00001025 int ret;
1026 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001027 mpi TA, TB;
1028
Paul Bakker6c591fa2011-05-05 11:49:20 +00001029 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001030
1031 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1032 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1033
Paul Bakker23986e52011-04-24 08:57:21 +00001034 for( i = A->n; i > 0; i-- )
1035 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001036 break;
1037
Paul Bakker23986e52011-04-24 08:57:21 +00001038 for( j = B->n; j > 0; j-- )
1039 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001040 break;
1041
Paul Bakker23986e52011-04-24 08:57:21 +00001042 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001043 MPI_CHK( mpi_lset( X, 0 ) );
1044
Paul Bakker23986e52011-04-24 08:57:21 +00001045 for( i++; j > 0; j-- )
1046 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001047
1048 X->s = A->s * B->s;
1049
1050cleanup:
1051
Paul Bakker6c591fa2011-05-05 11:49:20 +00001052 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001053
1054 return( ret );
1055}
1056
1057/*
1058 * Baseline multiplication: X = A * b
1059 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001060int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001061{
1062 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001063 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001064
1065 _B.s = 1;
1066 _B.n = 1;
1067 _B.p = p;
1068 p[0] = b;
1069
1070 return( mpi_mul_mpi( X, A, &_B ) );
1071}
1072
1073/*
1074 * Division by mpi: A = Q * B + R (HAC 14.20)
1075 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001076int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001077{
Paul Bakker23986e52011-04-24 08:57:21 +00001078 int ret;
1079 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001080 mpi X, Y, Z, T1, T2;
1081
1082 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001083 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001084
Paul Bakker6c591fa2011-05-05 11:49:20 +00001085 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1086 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001087
1088 if( mpi_cmp_abs( A, B ) < 0 )
1089 {
1090 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1091 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1092 return( 0 );
1093 }
1094
1095 MPI_CHK( mpi_copy( &X, A ) );
1096 MPI_CHK( mpi_copy( &Y, B ) );
1097 X.s = Y.s = 1;
1098
1099 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1100 MPI_CHK( mpi_lset( &Z, 0 ) );
1101 MPI_CHK( mpi_grow( &T1, 2 ) );
1102 MPI_CHK( mpi_grow( &T2, 3 ) );
1103
1104 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001105 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001106 {
1107 k = biL - 1 - k;
1108 MPI_CHK( mpi_shift_l( &X, k ) );
1109 MPI_CHK( mpi_shift_l( &Y, k ) );
1110 }
1111 else k = 0;
1112
1113 n = X.n - 1;
1114 t = Y.n - 1;
Paul Bakkerc110d022012-10-19 12:15:08 +00001115 MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001116
1117 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1118 {
1119 Z.p[n - t]++;
1120 mpi_sub_mpi( &X, &X, &Y );
1121 }
1122 mpi_shift_r( &Y, biL * (n - t) );
1123
1124 for( i = n; i > t ; i-- )
1125 {
1126 if( X.p[i] >= Y.p[t] )
1127 Z.p[i - t - 1] = ~0;
1128 else
1129 {
Paul Bakker62261d62012-10-02 12:19:31 +00001130#if defined(POLARSSL_HAVE_UDBL)
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001131 t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001132
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001133 r = (t_udbl) X.p[i] << biL;
1134 r |= (t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001135 r /= Y.p[t];
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001136 if( r > ((t_udbl) 1 << biL) - 1)
1137 r = ((t_udbl) 1 << biL) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001138
Paul Bakkera755ca12011-04-24 09:11:17 +00001139 Z.p[i - t - 1] = (t_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001140#else
1141 /*
1142 * __udiv_qrnnd_c, from gmp/longlong.h
1143 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001144 t_uint q0, q1, r0, r1;
1145 t_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001146
1147 d = Y.p[t];
1148 d0 = ( d << biH ) >> biH;
1149 d1 = ( d >> biH );
1150
1151 q1 = X.p[i] / d1;
1152 r1 = X.p[i] - d1 * q1;
1153 r1 <<= biH;
1154 r1 |= ( X.p[i - 1] >> biH );
1155
1156 m = q1 * d0;
1157 if( r1 < m )
1158 {
1159 q1--, r1 += d;
1160 while( r1 >= d && r1 < m )
1161 q1--, r1 += d;
1162 }
1163 r1 -= m;
1164
1165 q0 = r1 / d1;
1166 r0 = r1 - d1 * q0;
1167 r0 <<= biH;
1168 r0 |= ( X.p[i - 1] << biH ) >> biH;
1169
1170 m = q0 * d0;
1171 if( r0 < m )
1172 {
1173 q0--, r0 += d;
1174 while( r0 >= d && r0 < m )
1175 q0--, r0 += d;
1176 }
1177 r0 -= m;
1178
1179 Z.p[i - t - 1] = ( q1 << biH ) | q0;
1180#endif
1181 }
1182
1183 Z.p[i - t - 1]++;
1184 do
1185 {
1186 Z.p[i - t - 1]--;
1187
1188 MPI_CHK( mpi_lset( &T1, 0 ) );
1189 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1190 T1.p[1] = Y.p[t];
1191 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1192
1193 MPI_CHK( mpi_lset( &T2, 0 ) );
1194 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1195 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1196 T2.p[2] = X.p[i];
1197 }
1198 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1199
1200 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1201 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1202 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1203
1204 if( mpi_cmp_int( &X, 0 ) < 0 )
1205 {
1206 MPI_CHK( mpi_copy( &T1, &Y ) );
1207 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1208 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1209 Z.p[i - t - 1]--;
1210 }
1211 }
1212
1213 if( Q != NULL )
1214 {
1215 mpi_copy( Q, &Z );
1216 Q->s = A->s * B->s;
1217 }
1218
1219 if( R != NULL )
1220 {
1221 mpi_shift_r( &X, k );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001222 X.s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001223 mpi_copy( R, &X );
1224
Paul Bakker5121ce52009-01-03 21:22:43 +00001225 if( mpi_cmp_int( R, 0 ) == 0 )
1226 R->s = 1;
1227 }
1228
1229cleanup:
1230
Paul Bakker6c591fa2011-05-05 11:49:20 +00001231 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1232 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001233
1234 return( ret );
1235}
1236
1237/*
1238 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001239 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001240int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001241{
1242 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001243 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001244
1245 p[0] = ( b < 0 ) ? -b : b;
1246 _B.s = ( b < 0 ) ? -1 : 1;
1247 _B.n = 1;
1248 _B.p = p;
1249
1250 return( mpi_div_mpi( Q, R, A, &_B ) );
1251}
1252
1253/*
1254 * Modulo: R = A mod B
1255 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001256int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001257{
1258 int ret;
1259
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001260 if( mpi_cmp_int( B, 0 ) < 0 )
1261 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1262
Paul Bakker5121ce52009-01-03 21:22:43 +00001263 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1264
1265 while( mpi_cmp_int( R, 0 ) < 0 )
1266 MPI_CHK( mpi_add_mpi( R, R, B ) );
1267
1268 while( mpi_cmp_mpi( R, B ) >= 0 )
1269 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1270
1271cleanup:
1272
1273 return( ret );
1274}
1275
1276/*
1277 * Modulo: r = A mod b
1278 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001279int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001280{
Paul Bakker23986e52011-04-24 08:57:21 +00001281 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001282 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001283
1284 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001285 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001286
1287 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001288 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001289
1290 /*
1291 * handle trivial cases
1292 */
1293 if( b == 1 )
1294 {
1295 *r = 0;
1296 return( 0 );
1297 }
1298
1299 if( b == 2 )
1300 {
1301 *r = A->p[0] & 1;
1302 return( 0 );
1303 }
1304
1305 /*
1306 * general case
1307 */
Paul Bakker23986e52011-04-24 08:57:21 +00001308 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001309 {
Paul Bakker23986e52011-04-24 08:57:21 +00001310 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001311 y = ( y << biH ) | ( x >> biH );
1312 z = y / b;
1313 y -= z * b;
1314
1315 x <<= biH;
1316 y = ( y << biH ) | ( x >> biH );
1317 z = y / b;
1318 y -= z * b;
1319 }
1320
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001321 /*
1322 * If A is negative, then the current y represents a negative value.
1323 * Flipping it to the positive side.
1324 */
1325 if( A->s < 0 && y != 0 )
1326 y = b - y;
1327
Paul Bakker5121ce52009-01-03 21:22:43 +00001328 *r = y;
1329
1330 return( 0 );
1331}
1332
1333/*
1334 * Fast Montgomery initialization (thanks to Tom St Denis)
1335 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001336static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001337{
Paul Bakkera755ca12011-04-24 09:11:17 +00001338 t_uint x, m0 = N->p[0];
Paul Bakker5121ce52009-01-03 21:22:43 +00001339
1340 x = m0;
1341 x += ( ( m0 + 2 ) & 4 ) << 1;
1342 x *= ( 2 - ( m0 * x ) );
1343
1344 if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
1345 if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
1346 if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
1347
1348 *mm = ~x + 1;
1349}
1350
1351/*
1352 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1353 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001354static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001355{
Paul Bakker23986e52011-04-24 08:57:21 +00001356 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001357 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001358
1359 memset( T->p, 0, T->n * ciL );
1360
1361 d = T->p;
1362 n = N->n;
1363 m = ( B->n < n ) ? B->n : n;
1364
1365 for( i = 0; i < n; i++ )
1366 {
1367 /*
1368 * T = (T + u0*B + u1*N) / 2^biL
1369 */
1370 u0 = A->p[i];
1371 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1372
1373 mpi_mul_hlp( m, B->p, d, u0 );
1374 mpi_mul_hlp( n, N->p, d, u1 );
1375
1376 *d++ = u0; d[n + 1] = 0;
1377 }
1378
1379 memcpy( A->p, d, (n + 1) * ciL );
1380
1381 if( mpi_cmp_abs( A, N ) >= 0 )
1382 mpi_sub_hlp( n, N->p, A->p );
1383 else
1384 /* prevent timing attacks */
1385 mpi_sub_hlp( n, A->p, T->p );
1386}
1387
1388/*
1389 * Montgomery reduction: A = A * R^-1 mod N
1390 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001391static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001392{
Paul Bakkera755ca12011-04-24 09:11:17 +00001393 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001394 mpi U;
1395
Paul Bakker8ddb6452013-02-27 14:56:33 +01001396 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001397 U.p = &z;
1398
1399 mpi_montmul( A, &U, N, mm, T );
1400}
1401
1402/*
1403 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1404 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001405int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001406{
Paul Bakker23986e52011-04-24 08:57:21 +00001407 int ret;
1408 size_t wbits, wsize, one = 1;
1409 size_t i, j, nblimbs;
1410 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001411 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001412 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1413 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001414
1415 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001416 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001417
Paul Bakkerf6198c12012-05-16 08:02:29 +00001418 if( mpi_cmp_int( E, 0 ) < 0 )
1419 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1420
1421 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001422 * Init temps and window size
1423 */
1424 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001425 mpi_init( &RR ); mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001426 memset( W, 0, sizeof( W ) );
1427
1428 i = mpi_msb( E );
1429
1430 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1431 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1432
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001433 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1434 wsize = POLARSSL_MPI_WINDOW_SIZE;
1435
Paul Bakker5121ce52009-01-03 21:22:43 +00001436 j = N->n + 1;
1437 MPI_CHK( mpi_grow( X, j ) );
1438 MPI_CHK( mpi_grow( &W[1], j ) );
1439 MPI_CHK( mpi_grow( &T, j * 2 ) );
1440
1441 /*
Paul Bakker50546922012-05-19 08:40:49 +00001442 * Compensate for negative A (and correct at the end)
1443 */
1444 neg = ( A->s == -1 );
1445
1446 mpi_init( &Apos );
1447 if( neg )
1448 {
1449 MPI_CHK( mpi_copy( &Apos, A ) );
1450 Apos.s = 1;
1451 A = &Apos;
1452 }
1453
1454 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001455 * If 1st call, pre-compute R^2 mod N
1456 */
1457 if( _RR == NULL || _RR->p == NULL )
1458 {
1459 MPI_CHK( mpi_lset( &RR, 1 ) );
1460 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1461 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1462
1463 if( _RR != NULL )
1464 memcpy( _RR, &RR, sizeof( mpi ) );
1465 }
1466 else
1467 memcpy( &RR, _RR, sizeof( mpi ) );
1468
1469 /*
1470 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1471 */
1472 if( mpi_cmp_mpi( A, N ) >= 0 )
1473 mpi_mod_mpi( &W[1], A, N );
1474 else mpi_copy( &W[1], A );
1475
1476 mpi_montmul( &W[1], &RR, N, mm, &T );
1477
1478 /*
1479 * X = R^2 * R^-1 mod N = R mod N
1480 */
1481 MPI_CHK( mpi_copy( X, &RR ) );
1482 mpi_montred( X, N, mm, &T );
1483
1484 if( wsize > 1 )
1485 {
1486 /*
1487 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1488 */
Paul Bakker23986e52011-04-24 08:57:21 +00001489 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001490
1491 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1492 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1493
1494 for( i = 0; i < wsize - 1; i++ )
1495 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001496
Paul Bakker5121ce52009-01-03 21:22:43 +00001497 /*
1498 * W[i] = W[i - 1] * W[1]
1499 */
Paul Bakker23986e52011-04-24 08:57:21 +00001500 for( i = j + 1; i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001501 {
1502 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1503 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1504
1505 mpi_montmul( &W[i], &W[1], N, mm, &T );
1506 }
1507 }
1508
1509 nblimbs = E->n;
1510 bufsize = 0;
1511 nbits = 0;
1512 wbits = 0;
1513 state = 0;
1514
1515 while( 1 )
1516 {
1517 if( bufsize == 0 )
1518 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001519 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001520 break;
1521
Paul Bakker0d7702c2013-10-29 16:18:35 +01001522 nblimbs--;
1523
Paul Bakkera755ca12011-04-24 09:11:17 +00001524 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001525 }
1526
1527 bufsize--;
1528
1529 ei = (E->p[nblimbs] >> bufsize) & 1;
1530
1531 /*
1532 * skip leading 0s
1533 */
1534 if( ei == 0 && state == 0 )
1535 continue;
1536
1537 if( ei == 0 && state == 1 )
1538 {
1539 /*
1540 * out of window, square X
1541 */
1542 mpi_montmul( X, X, N, mm, &T );
1543 continue;
1544 }
1545
1546 /*
1547 * add ei to current window
1548 */
1549 state = 2;
1550
1551 nbits++;
1552 wbits |= (ei << (wsize - nbits));
1553
1554 if( nbits == wsize )
1555 {
1556 /*
1557 * X = X^wsize R^-1 mod N
1558 */
1559 for( i = 0; i < wsize; i++ )
1560 mpi_montmul( X, X, N, mm, &T );
1561
1562 /*
1563 * X = X * W[wbits] R^-1 mod N
1564 */
1565 mpi_montmul( X, &W[wbits], N, mm, &T );
1566
1567 state--;
1568 nbits = 0;
1569 wbits = 0;
1570 }
1571 }
1572
1573 /*
1574 * process the remaining bits
1575 */
1576 for( i = 0; i < nbits; i++ )
1577 {
1578 mpi_montmul( X, X, N, mm, &T );
1579
1580 wbits <<= 1;
1581
Paul Bakker23986e52011-04-24 08:57:21 +00001582 if( (wbits & (one << wsize)) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001583 mpi_montmul( X, &W[1], N, mm, &T );
1584 }
1585
1586 /*
1587 * X = A^E * R * R^-1 mod N = A^E mod N
1588 */
1589 mpi_montred( X, N, mm, &T );
1590
Paul Bakkerf6198c12012-05-16 08:02:29 +00001591 if( neg )
1592 {
1593 X->s = -1;
1594 mpi_add_mpi( X, N, X );
1595 }
1596
Paul Bakker5121ce52009-01-03 21:22:43 +00001597cleanup:
1598
Paul Bakker23986e52011-04-24 08:57:21 +00001599 for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001600 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001601
Paul Bakkerf6198c12012-05-16 08:02:29 +00001602 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001603
1604 if( _RR == NULL )
1605 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001606
1607 return( ret );
1608}
1609
Paul Bakker5121ce52009-01-03 21:22:43 +00001610/*
1611 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1612 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001613int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001614{
Paul Bakker23986e52011-04-24 08:57:21 +00001615 int ret;
1616 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001617 mpi TG, TA, TB;
1618
Paul Bakker6c591fa2011-05-05 11:49:20 +00001619 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001620
Paul Bakker5121ce52009-01-03 21:22:43 +00001621 MPI_CHK( mpi_copy( &TA, A ) );
1622 MPI_CHK( mpi_copy( &TB, B ) );
1623
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001624 lz = mpi_lsb( &TA );
1625 lzt = mpi_lsb( &TB );
1626
1627 if ( lzt < lz )
1628 lz = lzt;
1629
1630 MPI_CHK( mpi_shift_r( &TA, lz ) );
1631 MPI_CHK( mpi_shift_r( &TB, lz ) );
1632
Paul Bakker5121ce52009-01-03 21:22:43 +00001633 TA.s = TB.s = 1;
1634
1635 while( mpi_cmp_int( &TA, 0 ) != 0 )
1636 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001637 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1638 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001639
1640 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1641 {
1642 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1643 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1644 }
1645 else
1646 {
1647 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1648 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1649 }
1650 }
1651
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001652 MPI_CHK( mpi_shift_l( &TB, lz ) );
1653 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001654
1655cleanup:
1656
Paul Bakker6c591fa2011-05-05 11:49:20 +00001657 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001658
1659 return( ret );
1660}
1661
Paul Bakkera3d195c2011-11-27 21:07:34 +00001662int mpi_fill_random( mpi *X, size_t size,
1663 int (*f_rng)(void *, unsigned char *, size_t),
1664 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001665{
Paul Bakker23986e52011-04-24 08:57:21 +00001666 int ret;
Paul Bakker287781a2011-03-26 13:18:49 +00001667
Paul Bakker39dfdac2012-02-12 17:17:27 +00001668 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001669 MPI_CHK( mpi_lset( X, 0 ) );
1670
Paul Bakker39dfdac2012-02-12 17:17:27 +00001671 MPI_CHK( f_rng( p_rng, (unsigned char *) X->p, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001672
1673cleanup:
1674 return( ret );
1675}
1676
Paul Bakker5121ce52009-01-03 21:22:43 +00001677/*
1678 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1679 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001680int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001681{
1682 int ret;
1683 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1684
1685 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001686 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001687
Paul Bakker6c591fa2011-05-05 11:49:20 +00001688 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1689 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1690 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001691
1692 MPI_CHK( mpi_gcd( &G, A, N ) );
1693
1694 if( mpi_cmp_int( &G, 1 ) != 0 )
1695 {
Paul Bakker40e46942009-01-03 21:51:57 +00001696 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001697 goto cleanup;
1698 }
1699
1700 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1701 MPI_CHK( mpi_copy( &TU, &TA ) );
1702 MPI_CHK( mpi_copy( &TB, N ) );
1703 MPI_CHK( mpi_copy( &TV, N ) );
1704
1705 MPI_CHK( mpi_lset( &U1, 1 ) );
1706 MPI_CHK( mpi_lset( &U2, 0 ) );
1707 MPI_CHK( mpi_lset( &V1, 0 ) );
1708 MPI_CHK( mpi_lset( &V2, 1 ) );
1709
1710 do
1711 {
1712 while( ( TU.p[0] & 1 ) == 0 )
1713 {
1714 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1715
1716 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1717 {
1718 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1719 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1720 }
1721
1722 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1723 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1724 }
1725
1726 while( ( TV.p[0] & 1 ) == 0 )
1727 {
1728 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1729
1730 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1731 {
1732 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1733 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1734 }
1735
1736 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1737 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1738 }
1739
1740 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1741 {
1742 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1743 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1744 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1745 }
1746 else
1747 {
1748 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1749 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1750 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1751 }
1752 }
1753 while( mpi_cmp_int( &TU, 0 ) != 0 );
1754
1755 while( mpi_cmp_int( &V1, 0 ) < 0 )
1756 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1757
1758 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1759 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1760
1761 MPI_CHK( mpi_copy( X, &V1 ) );
1762
1763cleanup:
1764
Paul Bakker6c591fa2011-05-05 11:49:20 +00001765 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1766 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1767 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001768
1769 return( ret );
1770}
1771
Paul Bakkerd9374b02012-11-02 11:02:58 +00001772#if defined(POLARSSL_GENPRIME)
1773
Paul Bakker5121ce52009-01-03 21:22:43 +00001774static const int small_prime[] =
1775{
1776 3, 5, 7, 11, 13, 17, 19, 23,
1777 29, 31, 37, 41, 43, 47, 53, 59,
1778 61, 67, 71, 73, 79, 83, 89, 97,
1779 101, 103, 107, 109, 113, 127, 131, 137,
1780 139, 149, 151, 157, 163, 167, 173, 179,
1781 181, 191, 193, 197, 199, 211, 223, 227,
1782 229, 233, 239, 241, 251, 257, 263, 269,
1783 271, 277, 281, 283, 293, 307, 311, 313,
1784 317, 331, 337, 347, 349, 353, 359, 367,
1785 373, 379, 383, 389, 397, 401, 409, 419,
1786 421, 431, 433, 439, 443, 449, 457, 461,
1787 463, 467, 479, 487, 491, 499, 503, 509,
1788 521, 523, 541, 547, 557, 563, 569, 571,
1789 577, 587, 593, 599, 601, 607, 613, 617,
1790 619, 631, 641, 643, 647, 653, 659, 661,
1791 673, 677, 683, 691, 701, 709, 719, 727,
1792 733, 739, 743, 751, 757, 761, 769, 773,
1793 787, 797, 809, 811, 821, 823, 827, 829,
1794 839, 853, 857, 859, 863, 877, 881, 883,
1795 887, 907, 911, 919, 929, 937, 941, 947,
1796 953, 967, 971, 977, 983, 991, 997, -103
1797};
1798
1799/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001800 * Small divisors test (X must be positive)
1801 *
1802 * Return values:
1803 * 0: no small factor (possible prime, more tests needed)
1804 * 1: certain prime
1805 * POLARSSL_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
1806 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00001807 */
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001808static int mpi_check_small_factors( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00001809{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001810 int ret = 0;
1811 size_t i;
1812 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001813
Paul Bakker5121ce52009-01-03 21:22:43 +00001814 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001815 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001816
1817 for( i = 0; small_prime[i] > 0; i++ )
1818 {
Paul Bakker5121ce52009-01-03 21:22:43 +00001819 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001820 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001821
1822 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1823
1824 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001825 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001826 }
1827
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001828cleanup:
1829 return( ret );
1830}
1831
1832/*
1833 * Miller-Rabin pseudo-primality test (HAC 4.24)
1834 */
1835static int mpi_miller_rabin( const mpi *X,
1836 int (*f_rng)(void *, unsigned char *, size_t),
1837 void *p_rng )
1838{
1839 int ret;
1840 size_t i, j, n, s;
1841 mpi W, R, T, A, RR;
1842
1843 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
1844 mpi_init( &RR );
1845
Paul Bakker5121ce52009-01-03 21:22:43 +00001846 /*
1847 * W = |X| - 1
1848 * R = W >> lsb( W )
1849 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001850 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001851 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001852 MPI_CHK( mpi_copy( &R, &W ) );
1853 MPI_CHK( mpi_shift_r( &R, s ) );
1854
1855 i = mpi_msb( X );
1856 /*
1857 * HAC, table 4.4
1858 */
1859 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1860 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1861 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1862
1863 for( i = 0; i < n; i++ )
1864 {
1865 /*
1866 * pick a random A, 1 < A < |X| - 1
1867 */
Paul Bakker901c6562012-04-20 13:25:38 +00001868 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001869
Paul Bakkerb94081b2011-01-05 15:53:06 +00001870 if( mpi_cmp_mpi( &A, &W ) >= 0 )
1871 {
1872 j = mpi_msb( &A ) - mpi_msb( &W );
1873 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1874 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001875 A.p[0] |= 3;
1876
1877 /*
1878 * A = A^R mod |X|
1879 */
1880 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1881
1882 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1883 mpi_cmp_int( &A, 1 ) == 0 )
1884 continue;
1885
1886 j = 1;
1887 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1888 {
1889 /*
1890 * A = A * A mod |X|
1891 */
1892 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1893 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1894
1895 if( mpi_cmp_int( &A, 1 ) == 0 )
1896 break;
1897
1898 j++;
1899 }
1900
1901 /*
1902 * not prime if A != |X| - 1 or A == 1
1903 */
1904 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1905 mpi_cmp_int( &A, 1 ) == 0 )
1906 {
Paul Bakker40e46942009-01-03 21:51:57 +00001907 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001908 break;
1909 }
1910 }
1911
1912cleanup:
Paul Bakker6c591fa2011-05-05 11:49:20 +00001913 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
1914 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001915
1916 return( ret );
1917}
1918
1919/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001920 * Pseudo-primality test: small factors, then Miller-Rabin
1921 */
Paul Bakker45f457d2013-11-25 14:26:52 +01001922int mpi_is_prime( mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001923 int (*f_rng)(void *, unsigned char *, size_t),
1924 void *p_rng )
1925{
1926 int ret;
1927 const mpi XX = { 1, X->n, X->p }; /* Abs(X) */
1928
1929 if( mpi_cmp_int( &XX, 0 ) == 0 ||
1930 mpi_cmp_int( &XX, 1 ) == 0 )
1931 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1932
1933 if( mpi_cmp_int( &XX, 2 ) == 0 )
1934 return( 0 );
1935
1936 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
1937 {
1938 if( ret == 1 )
1939 return( 0 );
1940
1941 return( ret );
1942 }
1943
1944 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
1945}
1946
1947/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001948 * Prime number generation
1949 */
Paul Bakker23986e52011-04-24 08:57:21 +00001950int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001951 int (*f_rng)(void *, unsigned char *, size_t),
1952 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001953{
Paul Bakker23986e52011-04-24 08:57:21 +00001954 int ret;
1955 size_t k, n;
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01001956 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001957 mpi Y;
1958
Paul Bakkerfe3256e2011-11-25 12:11:43 +00001959 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00001960 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001961
Paul Bakker6c591fa2011-05-05 11:49:20 +00001962 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001963
1964 n = BITS_TO_LIMBS( nbits );
1965
Paul Bakker901c6562012-04-20 13:25:38 +00001966 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001967
1968 k = mpi_msb( X );
1969 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
1970 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
1971
1972 X->p[0] |= 3;
1973
1974 if( dh_flag == 0 )
1975 {
1976 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
1977 {
Paul Bakker40e46942009-01-03 21:51:57 +00001978 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001979 goto cleanup;
1980
1981 MPI_CHK( mpi_add_int( X, X, 2 ) );
1982 }
1983 }
1984 else
1985 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01001986 /*
1987 * An necessary condition for Y and X = 2Y + 1 to be prime
1988 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
1989 * Make sure it is satisfied, while keeping X = 3 mod 4
1990 */
1991 MPI_CHK( mpi_mod_int( &r, X, 3 ) );
1992 if( r == 0 )
1993 MPI_CHK( mpi_add_int( X, X, 8 ) );
1994 else if( r == 1 )
1995 MPI_CHK( mpi_add_int( X, X, 4 ) );
1996
1997 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
1998 MPI_CHK( mpi_copy( &Y, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001999 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2000
2001 while( 1 )
2002 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002003 /*
2004 * First, check small factors for X and Y
2005 * before doing Miller-Rabin on any of them
2006 */
2007 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2008 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2009 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2010 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002011 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002012 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002013 }
2014
Paul Bakker40e46942009-01-03 21:51:57 +00002015 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002016 goto cleanup;
2017
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002018 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002019 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002020 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2021 * so up Y by 6 and X by 12.
2022 */
2023 MPI_CHK( mpi_add_int( X, X, 12 ) );
2024 MPI_CHK( mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002025 }
2026 }
2027
2028cleanup:
2029
Paul Bakker6c591fa2011-05-05 11:49:20 +00002030 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002031
2032 return( ret );
2033}
2034
Manuel Pégourié-Gonnarddf0142b2013-08-22 18:29:07 +02002035#endif /* POLARSSL_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002036
Paul Bakker40e46942009-01-03 21:51:57 +00002037#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002038
Paul Bakker23986e52011-04-24 08:57:21 +00002039#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002040
2041static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2042{
2043 { 693, 609, 21 },
2044 { 1764, 868, 28 },
2045 { 768454923, 542167814, 1 }
2046};
2047
Paul Bakker5121ce52009-01-03 21:22:43 +00002048/*
2049 * Checkup routine
2050 */
2051int mpi_self_test( int verbose )
2052{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002053 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002054 mpi A, E, N, X, Y, U, V;
2055
Paul Bakker6c591fa2011-05-05 11:49:20 +00002056 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2057 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002058
2059 MPI_CHK( mpi_read_string( &A, 16,
2060 "EFE021C2645FD1DC586E69184AF4A31E" \
2061 "D5F53E93B5F123FA41680867BA110131" \
2062 "944FE7952E2517337780CB0DB80E61AA" \
2063 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2064
2065 MPI_CHK( mpi_read_string( &E, 16,
2066 "B2E7EFD37075B9F03FF989C7C5051C20" \
2067 "34D2A323810251127E7BF8625A4F49A5" \
2068 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2069 "5B5C25763222FEFCCFC38B832366C29E" ) );
2070
2071 MPI_CHK( mpi_read_string( &N, 16,
2072 "0066A198186C18C10B2F5ED9B522752A" \
2073 "9830B69916E535C8F047518A889A43A5" \
2074 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2075
2076 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2077
2078 MPI_CHK( mpi_read_string( &U, 16,
2079 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2080 "9E857EA95A03512E2BAE7391688D264A" \
2081 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2082 "8001B72E848A38CAE1C65F78E56ABDEF" \
2083 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2084 "ECF677152EF804370C1A305CAF3B5BF1" \
2085 "30879B56C61DE584A0F53A2447A51E" ) );
2086
2087 if( verbose != 0 )
2088 printf( " MPI test #1 (mul_mpi): " );
2089
2090 if( mpi_cmp_mpi( &X, &U ) != 0 )
2091 {
2092 if( verbose != 0 )
2093 printf( "failed\n" );
2094
2095 return( 1 );
2096 }
2097
2098 if( verbose != 0 )
2099 printf( "passed\n" );
2100
2101 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2102
2103 MPI_CHK( mpi_read_string( &U, 16,
2104 "256567336059E52CAE22925474705F39A94" ) );
2105
2106 MPI_CHK( mpi_read_string( &V, 16,
2107 "6613F26162223DF488E9CD48CC132C7A" \
2108 "0AC93C701B001B092E4E5B9F73BCD27B" \
2109 "9EE50D0657C77F374E903CDFA4C642" ) );
2110
2111 if( verbose != 0 )
2112 printf( " MPI test #2 (div_mpi): " );
2113
2114 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2115 mpi_cmp_mpi( &Y, &V ) != 0 )
2116 {
2117 if( verbose != 0 )
2118 printf( "failed\n" );
2119
2120 return( 1 );
2121 }
2122
2123 if( verbose != 0 )
2124 printf( "passed\n" );
2125
2126 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2127
2128 MPI_CHK( mpi_read_string( &U, 16,
2129 "36E139AEA55215609D2816998ED020BB" \
2130 "BD96C37890F65171D948E9BC7CBAA4D9" \
2131 "325D24D6A3C12710F10A09FA08AB87" ) );
2132
2133 if( verbose != 0 )
2134 printf( " MPI test #3 (exp_mod): " );
2135
2136 if( mpi_cmp_mpi( &X, &U ) != 0 )
2137 {
2138 if( verbose != 0 )
2139 printf( "failed\n" );
2140
2141 return( 1 );
2142 }
2143
2144 if( verbose != 0 )
2145 printf( "passed\n" );
2146
2147 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2148
2149 MPI_CHK( mpi_read_string( &U, 16,
2150 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2151 "C3DBA76456363A10869622EAC2DD84EC" \
2152 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2153
2154 if( verbose != 0 )
2155 printf( " MPI test #4 (inv_mod): " );
2156
2157 if( mpi_cmp_mpi( &X, &U ) != 0 )
2158 {
2159 if( verbose != 0 )
2160 printf( "failed\n" );
2161
2162 return( 1 );
2163 }
2164
2165 if( verbose != 0 )
2166 printf( "passed\n" );
2167
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002168 if( verbose != 0 )
2169 printf( " MPI test #5 (simple gcd): " );
2170
2171 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2172 {
2173 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002174 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002175
Paul Bakker23986e52011-04-24 08:57:21 +00002176 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002177
Paul Bakker23986e52011-04-24 08:57:21 +00002178 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2179 {
2180 if( verbose != 0 )
2181 printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002182
Paul Bakker23986e52011-04-24 08:57:21 +00002183 return( 1 );
2184 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002185 }
2186
2187 if( verbose != 0 )
2188 printf( "passed\n" );
2189
Paul Bakker5121ce52009-01-03 21:22:43 +00002190cleanup:
2191
2192 if( ret != 0 && verbose != 0 )
2193 printf( "Unexpected error, return code = %08X\n", ret );
2194
Paul Bakker6c591fa2011-05-05 11:49:20 +00002195 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2196 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002197
2198 if( verbose != 0 )
2199 printf( "\n" );
2200
2201 return( ret );
2202}
2203
2204#endif
2205
2206#endif