blob: 663d9240e20a792833ca539dd639941808d70bd4 [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/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100123 * Resize down as much as possible,
124 * while keeping at least the specified number of limbs
125 */
126int mpi_shrink( mpi *X, size_t nblimbs )
127{
128 t_uint *p;
129 size_t i;
130
131 /* Actually resize up in this case */
132 if( X->n <= nblimbs )
133 return( mpi_grow( X, nblimbs ) );
134
135 for( i = X->n - 1; i > 0; i-- )
136 if( X->p[i] != 0 )
137 break;
138 i++;
139
140 if( i < nblimbs )
141 i = nblimbs;
142
143 if( ( p = (t_uint *) polarssl_malloc( i * ciL ) ) == NULL )
144 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
145
146 memset( p, 0, i * ciL );
147
148 if( X->p != NULL )
149 {
150 memcpy( p, X->p, i * ciL );
151 memset( X->p, 0, X->n * ciL );
152 polarssl_free( X->p );
153 }
154
155 X->n = i;
156 X->p = p;
157
158 return( 0 );
159}
160
161/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000162 * Copy the contents of Y into X
163 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000164int mpi_copy( mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000165{
Paul Bakker23986e52011-04-24 08:57:21 +0000166 int ret;
167 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000168
169 if( X == Y )
170 return( 0 );
171
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200172 if( Y->p == NULL )
173 {
174 mpi_free( X );
175 return( 0 );
176 }
177
Paul Bakker5121ce52009-01-03 21:22:43 +0000178 for( i = Y->n - 1; i > 0; i-- )
179 if( Y->p[i] != 0 )
180 break;
181 i++;
182
183 X->s = Y->s;
184
185 MPI_CHK( mpi_grow( X, i ) );
186
187 memset( X->p, 0, X->n * ciL );
188 memcpy( X->p, Y->p, i * ciL );
189
190cleanup:
191
192 return( ret );
193}
194
195/*
196 * Swap the contents of X and Y
197 */
198void mpi_swap( mpi *X, mpi *Y )
199{
200 mpi T;
201
202 memcpy( &T, X, sizeof( mpi ) );
203 memcpy( X, Y, sizeof( mpi ) );
204 memcpy( Y, &T, sizeof( mpi ) );
205}
206
207/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100208 * Conditionally assign X = Y, without leaking information
209 */
210int mpi_safe_cond_assign( mpi *X, mpi *Y, unsigned char assign )
211{
212 int ret = 0;
213 size_t i;
214
215 if( assign * ( 1 - assign ) != 0 )
216 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
217
218 /* Make sure both MPIs have the same size */
219 if( X->n > Y->n )
220 MPI_CHK( mpi_grow( Y, X->n ) );
221 if( Y->n > X->n )
222 MPI_CHK( mpi_grow( X, Y->n ) );
223
224 /* Do the conditional assign safely */
225 for( i = 0; i < X->n; i++ )
226 X->p[i] = X->p[i] * (1 - assign) + Y->p[i] * assign;
227
228cleanup:
229 return( ret );
230}
231
232/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000233 * Set value from integer
234 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000235int mpi_lset( mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000236{
237 int ret;
238
239 MPI_CHK( mpi_grow( X, 1 ) );
240 memset( X->p, 0, X->n * ciL );
241
242 X->p[0] = ( z < 0 ) ? -z : z;
243 X->s = ( z < 0 ) ? -1 : 1;
244
245cleanup:
246
247 return( ret );
248}
249
250/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000251 * Get a specific bit
252 */
Paul Bakker6b906e52012-05-08 12:01:43 +0000253int mpi_get_bit( const mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000254{
255 if( X->n * biL <= pos )
256 return( 0 );
257
258 return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
259}
260
261/*
262 * Set a bit to a specific value of 0 or 1
263 */
264int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
265{
266 int ret = 0;
267 size_t off = pos / biL;
268 size_t idx = pos % biL;
269
270 if( val != 0 && val != 1 )
271 return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
272
273 if( X->n * biL <= pos )
274 {
275 if( val == 0 )
276 return ( 0 );
277
278 MPI_CHK( mpi_grow( X, off + 1 ) );
279 }
280
281 X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
282
283cleanup:
284
285 return( ret );
286}
287
288/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000289 * Return the number of least significant bits
290 */
Paul Bakker23986e52011-04-24 08:57:21 +0000291size_t mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000292{
Paul Bakker23986e52011-04-24 08:57:21 +0000293 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000294
295 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000296 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000297 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
298 return( count );
299
300 return( 0 );
301}
302
303/*
304 * Return the number of most significant bits
305 */
Paul Bakker23986e52011-04-24 08:57:21 +0000306size_t mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000307{
Paul Bakker23986e52011-04-24 08:57:21 +0000308 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000309
310 for( i = X->n - 1; i > 0; i-- )
311 if( X->p[i] != 0 )
312 break;
313
Paul Bakker23986e52011-04-24 08:57:21 +0000314 for( j = biL; j > 0; j-- )
315 if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000316 break;
317
Paul Bakker23986e52011-04-24 08:57:21 +0000318 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000319}
320
321/*
322 * Return the total size in bytes
323 */
Paul Bakker23986e52011-04-24 08:57:21 +0000324size_t mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000325{
326 return( ( mpi_msb( X ) + 7 ) >> 3 );
327}
328
329/*
330 * Convert an ASCII character to digit value
331 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000332static int mpi_get_digit( t_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000333{
334 *d = 255;
335
336 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
337 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
338 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
339
Paul Bakkera755ca12011-04-24 09:11:17 +0000340 if( *d >= (t_uint) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000341 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000342
343 return( 0 );
344}
345
346/*
347 * Import from an ASCII string
348 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000349int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000350{
Paul Bakker23986e52011-04-24 08:57:21 +0000351 int ret;
352 size_t i, j, slen, n;
Paul Bakkera755ca12011-04-24 09:11:17 +0000353 t_uint d;
Paul Bakker5121ce52009-01-03 21:22:43 +0000354 mpi T;
355
356 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000357 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000358
Paul Bakker6c591fa2011-05-05 11:49:20 +0000359 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000360
Paul Bakkerff60ee62010-03-16 21:09:09 +0000361 slen = strlen( s );
362
Paul Bakker5121ce52009-01-03 21:22:43 +0000363 if( radix == 16 )
364 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000365 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000366
367 MPI_CHK( mpi_grow( X, n ) );
368 MPI_CHK( mpi_lset( X, 0 ) );
369
Paul Bakker23986e52011-04-24 08:57:21 +0000370 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000371 {
Paul Bakker23986e52011-04-24 08:57:21 +0000372 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000373 {
374 X->s = -1;
375 break;
376 }
377
Paul Bakker23986e52011-04-24 08:57:21 +0000378 MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
380 }
381 }
382 else
383 {
384 MPI_CHK( mpi_lset( X, 0 ) );
385
Paul Bakkerff60ee62010-03-16 21:09:09 +0000386 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 {
388 if( i == 0 && s[i] == '-' )
389 {
390 X->s = -1;
391 continue;
392 }
393
394 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
395 MPI_CHK( mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000396
397 if( X->s == 1 )
398 {
399 MPI_CHK( mpi_add_int( X, &T, d ) );
400 }
401 else
402 {
403 MPI_CHK( mpi_sub_int( X, &T, d ) );
404 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000405 }
406 }
407
408cleanup:
409
Paul Bakker6c591fa2011-05-05 11:49:20 +0000410 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000411
412 return( ret );
413}
414
415/*
416 * Helper to write the digits high-order first
417 */
418static int mpi_write_hlp( mpi *X, int radix, char **p )
419{
420 int ret;
Paul Bakkera755ca12011-04-24 09:11:17 +0000421 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000422
423 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000424 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000425
426 MPI_CHK( mpi_mod_int( &r, X, radix ) );
427 MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
428
429 if( mpi_cmp_int( X, 0 ) != 0 )
430 MPI_CHK( mpi_write_hlp( X, radix, p ) );
431
432 if( r < 10 )
433 *(*p)++ = (char)( r + 0x30 );
434 else
435 *(*p)++ = (char)( r + 0x37 );
436
437cleanup:
438
439 return( ret );
440}
441
442/*
443 * Export into an ASCII string
444 */
Paul Bakker23986e52011-04-24 08:57:21 +0000445int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000446{
Paul Bakker23986e52011-04-24 08:57:21 +0000447 int ret = 0;
448 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000449 char *p;
450 mpi T;
451
452 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000453 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000454
455 n = mpi_msb( X );
456 if( radix >= 4 ) n >>= 1;
457 if( radix >= 16 ) n >>= 1;
458 n += 3;
459
460 if( *slen < n )
461 {
462 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000463 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000464 }
465
466 p = s;
Paul Bakker6c591fa2011-05-05 11:49:20 +0000467 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000468
469 if( X->s == -1 )
470 *p++ = '-';
471
472 if( radix == 16 )
473 {
Paul Bakker23986e52011-04-24 08:57:21 +0000474 int c;
475 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000476
Paul Bakker23986e52011-04-24 08:57:21 +0000477 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000478 {
Paul Bakker23986e52011-04-24 08:57:21 +0000479 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000480 {
Paul Bakker23986e52011-04-24 08:57:21 +0000481 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000482
Paul Bakker23986e52011-04-24 08:57:21 +0000483 if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000484 continue;
485
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000486 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000487 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000488 k = 1;
489 }
490 }
491 }
492 else
493 {
494 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000495
496 if( T.s == -1 )
497 T.s = 1;
498
Paul Bakker5121ce52009-01-03 21:22:43 +0000499 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
500 }
501
502 *p++ = '\0';
503 *slen = p - s;
504
505cleanup:
506
Paul Bakker6c591fa2011-05-05 11:49:20 +0000507 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000508
509 return( ret );
510}
511
Paul Bakker335db3f2011-04-25 15:28:35 +0000512#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000513/*
514 * Read X from an opened file
515 */
516int mpi_read_file( mpi *X, int radix, FILE *fin )
517{
Paul Bakkera755ca12011-04-24 09:11:17 +0000518 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000519 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000520 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000521 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000522 * Buffer should have space for (short) label and decimal formatted MPI,
523 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000524 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000525 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000526
527 memset( s, 0, sizeof( s ) );
528 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000529 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000530
531 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000532 if( slen == sizeof( s ) - 2 )
533 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
534
Paul Bakker5121ce52009-01-03 21:22:43 +0000535 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
536 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
537
538 p = s + slen;
539 while( --p >= s )
540 if( mpi_get_digit( &d, radix, *p ) != 0 )
541 break;
542
543 return( mpi_read_string( X, radix, p + 1 ) );
544}
545
546/*
547 * Write X into an opened file (or stdout if fout == NULL)
548 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000549int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000550{
Paul Bakker23986e52011-04-24 08:57:21 +0000551 int ret;
552 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000553 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000554 * Buffer should have space for (short) label and decimal formatted MPI,
555 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000556 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000557 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000558
559 n = sizeof( s );
560 memset( s, 0, n );
561 n -= 2;
562
Paul Bakker23986e52011-04-24 08:57:21 +0000563 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000564
565 if( p == NULL ) p = "";
566
567 plen = strlen( p );
568 slen = strlen( s );
569 s[slen++] = '\r';
570 s[slen++] = '\n';
571
572 if( fout != NULL )
573 {
574 if( fwrite( p, 1, plen, fout ) != plen ||
575 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000576 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000577 }
578 else
579 printf( "%s%s", p, s );
580
581cleanup:
582
583 return( ret );
584}
Paul Bakker335db3f2011-04-25 15:28:35 +0000585#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000586
587/*
588 * Import X from unsigned binary data, big endian
589 */
Paul Bakker23986e52011-04-24 08:57:21 +0000590int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000591{
Paul Bakker23986e52011-04-24 08:57:21 +0000592 int ret;
593 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000594
595 for( n = 0; n < buflen; n++ )
596 if( buf[n] != 0 )
597 break;
598
599 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
600 MPI_CHK( mpi_lset( X, 0 ) );
601
Paul Bakker23986e52011-04-24 08:57:21 +0000602 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000603 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000604
605cleanup:
606
607 return( ret );
608}
609
610/*
611 * Export X into unsigned binary data, big endian
612 */
Paul Bakker23986e52011-04-24 08:57:21 +0000613int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000614{
Paul Bakker23986e52011-04-24 08:57:21 +0000615 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000616
617 n = mpi_size( X );
618
619 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000620 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000621
622 memset( buf, 0, buflen );
623
624 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
625 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
626
627 return( 0 );
628}
629
630/*
631 * Left-shift: X <<= count
632 */
Paul Bakker23986e52011-04-24 08:57:21 +0000633int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000634{
Paul Bakker23986e52011-04-24 08:57:21 +0000635 int ret;
636 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000637 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000638
639 v0 = count / (biL );
640 t1 = count & (biL - 1);
641
642 i = mpi_msb( X ) + count;
643
Paul Bakkerf9688572011-05-05 10:00:45 +0000644 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000645 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
646
647 ret = 0;
648
649 /*
650 * shift by count / limb_size
651 */
652 if( v0 > 0 )
653 {
Paul Bakker23986e52011-04-24 08:57:21 +0000654 for( i = X->n; i > v0; i-- )
655 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000656
Paul Bakker23986e52011-04-24 08:57:21 +0000657 for( ; i > 0; i-- )
658 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000659 }
660
661 /*
662 * shift by count % limb_size
663 */
664 if( t1 > 0 )
665 {
666 for( i = v0; i < X->n; i++ )
667 {
668 r1 = X->p[i] >> (biL - t1);
669 X->p[i] <<= t1;
670 X->p[i] |= r0;
671 r0 = r1;
672 }
673 }
674
675cleanup:
676
677 return( ret );
678}
679
680/*
681 * Right-shift: X >>= count
682 */
Paul Bakker23986e52011-04-24 08:57:21 +0000683int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000684{
Paul Bakker23986e52011-04-24 08:57:21 +0000685 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000686 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000687
688 v0 = count / biL;
689 v1 = count & (biL - 1);
690
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100691 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
692 return mpi_lset( X, 0 );
693
Paul Bakker5121ce52009-01-03 21:22:43 +0000694 /*
695 * shift by count / limb_size
696 */
697 if( v0 > 0 )
698 {
699 for( i = 0; i < X->n - v0; i++ )
700 X->p[i] = X->p[i + v0];
701
702 for( ; i < X->n; i++ )
703 X->p[i] = 0;
704 }
705
706 /*
707 * shift by count % limb_size
708 */
709 if( v1 > 0 )
710 {
Paul Bakker23986e52011-04-24 08:57:21 +0000711 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000712 {
Paul Bakker23986e52011-04-24 08:57:21 +0000713 r1 = X->p[i - 1] << (biL - v1);
714 X->p[i - 1] >>= v1;
715 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000716 r0 = r1;
717 }
718 }
719
720 return( 0 );
721}
722
723/*
724 * Compare unsigned values
725 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000726int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000727{
Paul Bakker23986e52011-04-24 08:57:21 +0000728 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000729
Paul Bakker23986e52011-04-24 08:57:21 +0000730 for( i = X->n; i > 0; i-- )
731 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000732 break;
733
Paul Bakker23986e52011-04-24 08:57:21 +0000734 for( j = Y->n; j > 0; j-- )
735 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000736 break;
737
Paul Bakker23986e52011-04-24 08:57:21 +0000738 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000739 return( 0 );
740
741 if( i > j ) return( 1 );
742 if( j > i ) return( -1 );
743
Paul Bakker23986e52011-04-24 08:57:21 +0000744 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000745 {
Paul Bakker23986e52011-04-24 08:57:21 +0000746 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
747 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000748 }
749
750 return( 0 );
751}
752
753/*
754 * Compare signed values
755 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000756int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000757{
Paul Bakker23986e52011-04-24 08:57:21 +0000758 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000759
Paul Bakker23986e52011-04-24 08:57:21 +0000760 for( i = X->n; i > 0; i-- )
761 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000762 break;
763
Paul Bakker23986e52011-04-24 08:57:21 +0000764 for( j = Y->n; j > 0; j-- )
765 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000766 break;
767
Paul Bakker23986e52011-04-24 08:57:21 +0000768 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000769 return( 0 );
770
771 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000772 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000773
774 if( X->s > 0 && Y->s < 0 ) return( 1 );
775 if( Y->s > 0 && X->s < 0 ) return( -1 );
776
Paul Bakker23986e52011-04-24 08:57:21 +0000777 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000778 {
Paul Bakker23986e52011-04-24 08:57:21 +0000779 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
780 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000781 }
782
783 return( 0 );
784}
785
786/*
787 * Compare signed values
788 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000789int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000790{
791 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000792 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000793
794 *p = ( z < 0 ) ? -z : z;
795 Y.s = ( z < 0 ) ? -1 : 1;
796 Y.n = 1;
797 Y.p = p;
798
799 return( mpi_cmp_mpi( X, &Y ) );
800}
801
802/*
803 * Unsigned addition: X = |A| + |B| (HAC 14.7)
804 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000805int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000806{
Paul Bakker23986e52011-04-24 08:57:21 +0000807 int ret;
808 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000809 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000810
811 if( X == B )
812 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000813 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000814 }
815
816 if( X != A )
817 MPI_CHK( mpi_copy( X, A ) );
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000818
819 /*
820 * X should always be positive as a result of unsigned additions.
821 */
822 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000823
Paul Bakker23986e52011-04-24 08:57:21 +0000824 for( j = B->n; j > 0; j-- )
825 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000826 break;
827
Paul Bakker23986e52011-04-24 08:57:21 +0000828 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000829
830 o = B->p; p = X->p; c = 0;
831
Paul Bakker23986e52011-04-24 08:57:21 +0000832 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000833 {
834 *p += c; c = ( *p < c );
835 *p += *o; c += ( *p < *o );
836 }
837
838 while( c != 0 )
839 {
840 if( i >= X->n )
841 {
842 MPI_CHK( mpi_grow( X, i + 1 ) );
843 p = X->p + i;
844 }
845
Paul Bakker2d319fd2012-09-16 21:34:26 +0000846 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000847 }
848
849cleanup:
850
851 return( ret );
852}
853
854/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100855 * Helper for mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000856 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000857static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000858{
Paul Bakker23986e52011-04-24 08:57:21 +0000859 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000860 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000861
862 for( i = c = 0; i < n; i++, s++, d++ )
863 {
864 z = ( *d < c ); *d -= c;
865 c = ( *d < *s ) + z; *d -= *s;
866 }
867
868 while( c != 0 )
869 {
870 z = ( *d < c ); *d -= c;
871 c = z; i++; d++;
872 }
873}
874
875/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100876 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000877 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000878int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000879{
880 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000881 int ret;
882 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000883
884 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000885 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000886
Paul Bakker6c591fa2011-05-05 11:49:20 +0000887 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000888
889 if( X == B )
890 {
891 MPI_CHK( mpi_copy( &TB, B ) );
892 B = &TB;
893 }
894
895 if( X != A )
896 MPI_CHK( mpi_copy( X, A ) );
897
Paul Bakker1ef7a532009-06-20 10:50:55 +0000898 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100899 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000900 */
901 X->s = 1;
902
Paul Bakker5121ce52009-01-03 21:22:43 +0000903 ret = 0;
904
Paul Bakker23986e52011-04-24 08:57:21 +0000905 for( n = B->n; n > 0; n-- )
906 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000907 break;
908
Paul Bakker23986e52011-04-24 08:57:21 +0000909 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000910
911cleanup:
912
Paul Bakker6c591fa2011-05-05 11:49:20 +0000913 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000914
915 return( ret );
916}
917
918/*
919 * Signed addition: X = A + B
920 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000921int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000922{
923 int ret, s = A->s;
924
925 if( A->s * B->s < 0 )
926 {
927 if( mpi_cmp_abs( A, B ) >= 0 )
928 {
929 MPI_CHK( mpi_sub_abs( X, A, B ) );
930 X->s = s;
931 }
932 else
933 {
934 MPI_CHK( mpi_sub_abs( X, B, A ) );
935 X->s = -s;
936 }
937 }
938 else
939 {
940 MPI_CHK( mpi_add_abs( X, A, B ) );
941 X->s = s;
942 }
943
944cleanup:
945
946 return( ret );
947}
948
949/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100950 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +0000951 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000952int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000953{
954 int ret, s = A->s;
955
956 if( A->s * B->s > 0 )
957 {
958 if( mpi_cmp_abs( A, B ) >= 0 )
959 {
960 MPI_CHK( mpi_sub_abs( X, A, B ) );
961 X->s = s;
962 }
963 else
964 {
965 MPI_CHK( mpi_sub_abs( X, B, A ) );
966 X->s = -s;
967 }
968 }
969 else
970 {
971 MPI_CHK( mpi_add_abs( X, A, B ) );
972 X->s = s;
973 }
974
975cleanup:
976
977 return( ret );
978}
979
980/*
981 * Signed addition: X = A + b
982 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000983int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000984{
985 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000986 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000987
988 p[0] = ( b < 0 ) ? -b : b;
989 _B.s = ( b < 0 ) ? -1 : 1;
990 _B.n = 1;
991 _B.p = p;
992
993 return( mpi_add_mpi( X, A, &_B ) );
994}
995
996/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100997 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +0000998 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000999int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001000{
1001 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001002 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001003
1004 p[0] = ( b < 0 ) ? -b : b;
1005 _B.s = ( b < 0 ) ? -1 : 1;
1006 _B.n = 1;
1007 _B.p = p;
1008
1009 return( mpi_sub_mpi( X, A, &_B ) );
1010}
1011
1012/*
1013 * Helper for mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001014 */
1015static
1016#if defined(__APPLE__) && defined(__arm__)
1017/*
1018 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1019 * appears to need this to prevent bad ARM code generation at -O3.
1020 */
1021__attribute__ ((noinline))
1022#endif
1023void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001024{
Paul Bakkera755ca12011-04-24 09:11:17 +00001025 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001026
1027#if defined(MULADDC_HUIT)
1028 for( ; i >= 8; i -= 8 )
1029 {
1030 MULADDC_INIT
1031 MULADDC_HUIT
1032 MULADDC_STOP
1033 }
1034
1035 for( ; i > 0; i-- )
1036 {
1037 MULADDC_INIT
1038 MULADDC_CORE
1039 MULADDC_STOP
1040 }
1041#else
1042 for( ; i >= 16; i -= 16 )
1043 {
1044 MULADDC_INIT
1045 MULADDC_CORE MULADDC_CORE
1046 MULADDC_CORE MULADDC_CORE
1047 MULADDC_CORE MULADDC_CORE
1048 MULADDC_CORE MULADDC_CORE
1049
1050 MULADDC_CORE MULADDC_CORE
1051 MULADDC_CORE MULADDC_CORE
1052 MULADDC_CORE MULADDC_CORE
1053 MULADDC_CORE MULADDC_CORE
1054 MULADDC_STOP
1055 }
1056
1057 for( ; i >= 8; i -= 8 )
1058 {
1059 MULADDC_INIT
1060 MULADDC_CORE MULADDC_CORE
1061 MULADDC_CORE MULADDC_CORE
1062
1063 MULADDC_CORE MULADDC_CORE
1064 MULADDC_CORE MULADDC_CORE
1065 MULADDC_STOP
1066 }
1067
1068 for( ; i > 0; i-- )
1069 {
1070 MULADDC_INIT
1071 MULADDC_CORE
1072 MULADDC_STOP
1073 }
1074#endif
1075
1076 t++;
1077
1078 do {
1079 *d += c; c = ( *d < c ); d++;
1080 }
1081 while( c != 0 );
1082}
1083
1084/*
1085 * Baseline multiplication: X = A * B (HAC 14.12)
1086 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001087int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001088{
Paul Bakker23986e52011-04-24 08:57:21 +00001089 int ret;
1090 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001091 mpi TA, TB;
1092
Paul Bakker6c591fa2011-05-05 11:49:20 +00001093 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001094
1095 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1096 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1097
Paul Bakker23986e52011-04-24 08:57:21 +00001098 for( i = A->n; i > 0; i-- )
1099 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001100 break;
1101
Paul Bakker23986e52011-04-24 08:57:21 +00001102 for( j = B->n; j > 0; j-- )
1103 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001104 break;
1105
Paul Bakker23986e52011-04-24 08:57:21 +00001106 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001107 MPI_CHK( mpi_lset( X, 0 ) );
1108
Paul Bakker23986e52011-04-24 08:57:21 +00001109 for( i++; j > 0; j-- )
1110 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001111
1112 X->s = A->s * B->s;
1113
1114cleanup:
1115
Paul Bakker6c591fa2011-05-05 11:49:20 +00001116 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001117
1118 return( ret );
1119}
1120
1121/*
1122 * Baseline multiplication: X = A * b
1123 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001124int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001125{
1126 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001127 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001128
1129 _B.s = 1;
1130 _B.n = 1;
1131 _B.p = p;
1132 p[0] = b;
1133
1134 return( mpi_mul_mpi( X, A, &_B ) );
1135}
1136
1137/*
1138 * Division by mpi: A = Q * B + R (HAC 14.20)
1139 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001140int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001141{
Paul Bakker23986e52011-04-24 08:57:21 +00001142 int ret;
1143 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001144 mpi X, Y, Z, T1, T2;
1145
1146 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001147 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001148
Paul Bakker6c591fa2011-05-05 11:49:20 +00001149 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1150 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001151
1152 if( mpi_cmp_abs( A, B ) < 0 )
1153 {
1154 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1155 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1156 return( 0 );
1157 }
1158
1159 MPI_CHK( mpi_copy( &X, A ) );
1160 MPI_CHK( mpi_copy( &Y, B ) );
1161 X.s = Y.s = 1;
1162
1163 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1164 MPI_CHK( mpi_lset( &Z, 0 ) );
1165 MPI_CHK( mpi_grow( &T1, 2 ) );
1166 MPI_CHK( mpi_grow( &T2, 3 ) );
1167
1168 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001169 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001170 {
1171 k = biL - 1 - k;
1172 MPI_CHK( mpi_shift_l( &X, k ) );
1173 MPI_CHK( mpi_shift_l( &Y, k ) );
1174 }
1175 else k = 0;
1176
1177 n = X.n - 1;
1178 t = Y.n - 1;
Paul Bakkerc110d022012-10-19 12:15:08 +00001179 MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001180
1181 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1182 {
1183 Z.p[n - t]++;
1184 mpi_sub_mpi( &X, &X, &Y );
1185 }
1186 mpi_shift_r( &Y, biL * (n - t) );
1187
1188 for( i = n; i > t ; i-- )
1189 {
1190 if( X.p[i] >= Y.p[t] )
1191 Z.p[i - t - 1] = ~0;
1192 else
1193 {
Paul Bakker62261d62012-10-02 12:19:31 +00001194#if defined(POLARSSL_HAVE_UDBL)
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001195 t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001196
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001197 r = (t_udbl) X.p[i] << biL;
1198 r |= (t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001199 r /= Y.p[t];
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001200 if( r > ((t_udbl) 1 << biL) - 1)
1201 r = ((t_udbl) 1 << biL) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001202
Paul Bakkera755ca12011-04-24 09:11:17 +00001203 Z.p[i - t - 1] = (t_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001204#else
1205 /*
1206 * __udiv_qrnnd_c, from gmp/longlong.h
1207 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001208 t_uint q0, q1, r0, r1;
1209 t_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001210
1211 d = Y.p[t];
1212 d0 = ( d << biH ) >> biH;
1213 d1 = ( d >> biH );
1214
1215 q1 = X.p[i] / d1;
1216 r1 = X.p[i] - d1 * q1;
1217 r1 <<= biH;
1218 r1 |= ( X.p[i - 1] >> biH );
1219
1220 m = q1 * d0;
1221 if( r1 < m )
1222 {
1223 q1--, r1 += d;
1224 while( r1 >= d && r1 < m )
1225 q1--, r1 += d;
1226 }
1227 r1 -= m;
1228
1229 q0 = r1 / d1;
1230 r0 = r1 - d1 * q0;
1231 r0 <<= biH;
1232 r0 |= ( X.p[i - 1] << biH ) >> biH;
1233
1234 m = q0 * d0;
1235 if( r0 < m )
1236 {
1237 q0--, r0 += d;
1238 while( r0 >= d && r0 < m )
1239 q0--, r0 += d;
1240 }
1241 r0 -= m;
1242
1243 Z.p[i - t - 1] = ( q1 << biH ) | q0;
1244#endif
1245 }
1246
1247 Z.p[i - t - 1]++;
1248 do
1249 {
1250 Z.p[i - t - 1]--;
1251
1252 MPI_CHK( mpi_lset( &T1, 0 ) );
1253 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1254 T1.p[1] = Y.p[t];
1255 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1256
1257 MPI_CHK( mpi_lset( &T2, 0 ) );
1258 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1259 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1260 T2.p[2] = X.p[i];
1261 }
1262 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1263
1264 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1265 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1266 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1267
1268 if( mpi_cmp_int( &X, 0 ) < 0 )
1269 {
1270 MPI_CHK( mpi_copy( &T1, &Y ) );
1271 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1272 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1273 Z.p[i - t - 1]--;
1274 }
1275 }
1276
1277 if( Q != NULL )
1278 {
1279 mpi_copy( Q, &Z );
1280 Q->s = A->s * B->s;
1281 }
1282
1283 if( R != NULL )
1284 {
1285 mpi_shift_r( &X, k );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001286 X.s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001287 mpi_copy( R, &X );
1288
Paul Bakker5121ce52009-01-03 21:22:43 +00001289 if( mpi_cmp_int( R, 0 ) == 0 )
1290 R->s = 1;
1291 }
1292
1293cleanup:
1294
Paul Bakker6c591fa2011-05-05 11:49:20 +00001295 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1296 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001297
1298 return( ret );
1299}
1300
1301/*
1302 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001303 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001304int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001305{
1306 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001307 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001308
1309 p[0] = ( b < 0 ) ? -b : b;
1310 _B.s = ( b < 0 ) ? -1 : 1;
1311 _B.n = 1;
1312 _B.p = p;
1313
1314 return( mpi_div_mpi( Q, R, A, &_B ) );
1315}
1316
1317/*
1318 * Modulo: R = A mod B
1319 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001320int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001321{
1322 int ret;
1323
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001324 if( mpi_cmp_int( B, 0 ) < 0 )
1325 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1326
Paul Bakker5121ce52009-01-03 21:22:43 +00001327 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1328
1329 while( mpi_cmp_int( R, 0 ) < 0 )
1330 MPI_CHK( mpi_add_mpi( R, R, B ) );
1331
1332 while( mpi_cmp_mpi( R, B ) >= 0 )
1333 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1334
1335cleanup:
1336
1337 return( ret );
1338}
1339
1340/*
1341 * Modulo: r = A mod b
1342 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001343int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001344{
Paul Bakker23986e52011-04-24 08:57:21 +00001345 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001346 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001347
1348 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001349 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001350
1351 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001352 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001353
1354 /*
1355 * handle trivial cases
1356 */
1357 if( b == 1 )
1358 {
1359 *r = 0;
1360 return( 0 );
1361 }
1362
1363 if( b == 2 )
1364 {
1365 *r = A->p[0] & 1;
1366 return( 0 );
1367 }
1368
1369 /*
1370 * general case
1371 */
Paul Bakker23986e52011-04-24 08:57:21 +00001372 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001373 {
Paul Bakker23986e52011-04-24 08:57:21 +00001374 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001375 y = ( y << biH ) | ( x >> biH );
1376 z = y / b;
1377 y -= z * b;
1378
1379 x <<= biH;
1380 y = ( y << biH ) | ( x >> biH );
1381 z = y / b;
1382 y -= z * b;
1383 }
1384
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001385 /*
1386 * If A is negative, then the current y represents a negative value.
1387 * Flipping it to the positive side.
1388 */
1389 if( A->s < 0 && y != 0 )
1390 y = b - y;
1391
Paul Bakker5121ce52009-01-03 21:22:43 +00001392 *r = y;
1393
1394 return( 0 );
1395}
1396
1397/*
1398 * Fast Montgomery initialization (thanks to Tom St Denis)
1399 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001400static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001401{
Paul Bakkera755ca12011-04-24 09:11:17 +00001402 t_uint x, m0 = N->p[0];
Paul Bakker5121ce52009-01-03 21:22:43 +00001403
1404 x = m0;
1405 x += ( ( m0 + 2 ) & 4 ) << 1;
1406 x *= ( 2 - ( m0 * x ) );
1407
1408 if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
1409 if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
1410 if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
1411
1412 *mm = ~x + 1;
1413}
1414
1415/*
1416 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1417 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001418static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001419{
Paul Bakker23986e52011-04-24 08:57:21 +00001420 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001421 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001422
1423 memset( T->p, 0, T->n * ciL );
1424
1425 d = T->p;
1426 n = N->n;
1427 m = ( B->n < n ) ? B->n : n;
1428
1429 for( i = 0; i < n; i++ )
1430 {
1431 /*
1432 * T = (T + u0*B + u1*N) / 2^biL
1433 */
1434 u0 = A->p[i];
1435 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1436
1437 mpi_mul_hlp( m, B->p, d, u0 );
1438 mpi_mul_hlp( n, N->p, d, u1 );
1439
1440 *d++ = u0; d[n + 1] = 0;
1441 }
1442
1443 memcpy( A->p, d, (n + 1) * ciL );
1444
1445 if( mpi_cmp_abs( A, N ) >= 0 )
1446 mpi_sub_hlp( n, N->p, A->p );
1447 else
1448 /* prevent timing attacks */
1449 mpi_sub_hlp( n, A->p, T->p );
1450}
1451
1452/*
1453 * Montgomery reduction: A = A * R^-1 mod N
1454 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001455static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001456{
Paul Bakkera755ca12011-04-24 09:11:17 +00001457 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001458 mpi U;
1459
Paul Bakker8ddb6452013-02-27 14:56:33 +01001460 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001461 U.p = &z;
1462
1463 mpi_montmul( A, &U, N, mm, T );
1464}
1465
1466/*
1467 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1468 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001469int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001470{
Paul Bakker23986e52011-04-24 08:57:21 +00001471 int ret;
1472 size_t wbits, wsize, one = 1;
1473 size_t i, j, nblimbs;
1474 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001475 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001476 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1477 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001478
1479 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001480 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001481
Paul Bakkerf6198c12012-05-16 08:02:29 +00001482 if( mpi_cmp_int( E, 0 ) < 0 )
1483 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1484
1485 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001486 * Init temps and window size
1487 */
1488 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001489 mpi_init( &RR ); mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001490 memset( W, 0, sizeof( W ) );
1491
1492 i = mpi_msb( E );
1493
1494 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1495 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1496
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001497 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1498 wsize = POLARSSL_MPI_WINDOW_SIZE;
1499
Paul Bakker5121ce52009-01-03 21:22:43 +00001500 j = N->n + 1;
1501 MPI_CHK( mpi_grow( X, j ) );
1502 MPI_CHK( mpi_grow( &W[1], j ) );
1503 MPI_CHK( mpi_grow( &T, j * 2 ) );
1504
1505 /*
Paul Bakker50546922012-05-19 08:40:49 +00001506 * Compensate for negative A (and correct at the end)
1507 */
1508 neg = ( A->s == -1 );
1509
1510 mpi_init( &Apos );
1511 if( neg )
1512 {
1513 MPI_CHK( mpi_copy( &Apos, A ) );
1514 Apos.s = 1;
1515 A = &Apos;
1516 }
1517
1518 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001519 * If 1st call, pre-compute R^2 mod N
1520 */
1521 if( _RR == NULL || _RR->p == NULL )
1522 {
1523 MPI_CHK( mpi_lset( &RR, 1 ) );
1524 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1525 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1526
1527 if( _RR != NULL )
1528 memcpy( _RR, &RR, sizeof( mpi ) );
1529 }
1530 else
1531 memcpy( &RR, _RR, sizeof( mpi ) );
1532
1533 /*
1534 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1535 */
1536 if( mpi_cmp_mpi( A, N ) >= 0 )
1537 mpi_mod_mpi( &W[1], A, N );
1538 else mpi_copy( &W[1], A );
1539
1540 mpi_montmul( &W[1], &RR, N, mm, &T );
1541
1542 /*
1543 * X = R^2 * R^-1 mod N = R mod N
1544 */
1545 MPI_CHK( mpi_copy( X, &RR ) );
1546 mpi_montred( X, N, mm, &T );
1547
1548 if( wsize > 1 )
1549 {
1550 /*
1551 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1552 */
Paul Bakker23986e52011-04-24 08:57:21 +00001553 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001554
1555 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1556 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1557
1558 for( i = 0; i < wsize - 1; i++ )
1559 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001560
Paul Bakker5121ce52009-01-03 21:22:43 +00001561 /*
1562 * W[i] = W[i - 1] * W[1]
1563 */
Paul Bakker23986e52011-04-24 08:57:21 +00001564 for( i = j + 1; i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001565 {
1566 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1567 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1568
1569 mpi_montmul( &W[i], &W[1], N, mm, &T );
1570 }
1571 }
1572
1573 nblimbs = E->n;
1574 bufsize = 0;
1575 nbits = 0;
1576 wbits = 0;
1577 state = 0;
1578
1579 while( 1 )
1580 {
1581 if( bufsize == 0 )
1582 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001583 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001584 break;
1585
Paul Bakker0d7702c2013-10-29 16:18:35 +01001586 nblimbs--;
1587
Paul Bakkera755ca12011-04-24 09:11:17 +00001588 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001589 }
1590
1591 bufsize--;
1592
1593 ei = (E->p[nblimbs] >> bufsize) & 1;
1594
1595 /*
1596 * skip leading 0s
1597 */
1598 if( ei == 0 && state == 0 )
1599 continue;
1600
1601 if( ei == 0 && state == 1 )
1602 {
1603 /*
1604 * out of window, square X
1605 */
1606 mpi_montmul( X, X, N, mm, &T );
1607 continue;
1608 }
1609
1610 /*
1611 * add ei to current window
1612 */
1613 state = 2;
1614
1615 nbits++;
1616 wbits |= (ei << (wsize - nbits));
1617
1618 if( nbits == wsize )
1619 {
1620 /*
1621 * X = X^wsize R^-1 mod N
1622 */
1623 for( i = 0; i < wsize; i++ )
1624 mpi_montmul( X, X, N, mm, &T );
1625
1626 /*
1627 * X = X * W[wbits] R^-1 mod N
1628 */
1629 mpi_montmul( X, &W[wbits], N, mm, &T );
1630
1631 state--;
1632 nbits = 0;
1633 wbits = 0;
1634 }
1635 }
1636
1637 /*
1638 * process the remaining bits
1639 */
1640 for( i = 0; i < nbits; i++ )
1641 {
1642 mpi_montmul( X, X, N, mm, &T );
1643
1644 wbits <<= 1;
1645
Paul Bakker23986e52011-04-24 08:57:21 +00001646 if( (wbits & (one << wsize)) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001647 mpi_montmul( X, &W[1], N, mm, &T );
1648 }
1649
1650 /*
1651 * X = A^E * R * R^-1 mod N = A^E mod N
1652 */
1653 mpi_montred( X, N, mm, &T );
1654
Paul Bakkerf6198c12012-05-16 08:02:29 +00001655 if( neg )
1656 {
1657 X->s = -1;
1658 mpi_add_mpi( X, N, X );
1659 }
1660
Paul Bakker5121ce52009-01-03 21:22:43 +00001661cleanup:
1662
Paul Bakker23986e52011-04-24 08:57:21 +00001663 for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001664 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001665
Paul Bakkerf6198c12012-05-16 08:02:29 +00001666 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001667
1668 if( _RR == NULL )
1669 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001670
1671 return( ret );
1672}
1673
Paul Bakker5121ce52009-01-03 21:22:43 +00001674/*
1675 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1676 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001677int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001678{
Paul Bakker23986e52011-04-24 08:57:21 +00001679 int ret;
1680 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001681 mpi TG, TA, TB;
1682
Paul Bakker6c591fa2011-05-05 11:49:20 +00001683 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001684
Paul Bakker5121ce52009-01-03 21:22:43 +00001685 MPI_CHK( mpi_copy( &TA, A ) );
1686 MPI_CHK( mpi_copy( &TB, B ) );
1687
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001688 lz = mpi_lsb( &TA );
1689 lzt = mpi_lsb( &TB );
1690
1691 if ( lzt < lz )
1692 lz = lzt;
1693
1694 MPI_CHK( mpi_shift_r( &TA, lz ) );
1695 MPI_CHK( mpi_shift_r( &TB, lz ) );
1696
Paul Bakker5121ce52009-01-03 21:22:43 +00001697 TA.s = TB.s = 1;
1698
1699 while( mpi_cmp_int( &TA, 0 ) != 0 )
1700 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001701 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1702 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001703
1704 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1705 {
1706 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1707 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1708 }
1709 else
1710 {
1711 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1712 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1713 }
1714 }
1715
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001716 MPI_CHK( mpi_shift_l( &TB, lz ) );
1717 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001718
1719cleanup:
1720
Paul Bakker6c591fa2011-05-05 11:49:20 +00001721 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001722
1723 return( ret );
1724}
1725
Paul Bakkera3d195c2011-11-27 21:07:34 +00001726int mpi_fill_random( mpi *X, size_t size,
1727 int (*f_rng)(void *, unsigned char *, size_t),
1728 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001729{
Paul Bakker23986e52011-04-24 08:57:21 +00001730 int ret;
Paul Bakker287781a2011-03-26 13:18:49 +00001731
Paul Bakker39dfdac2012-02-12 17:17:27 +00001732 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001733 MPI_CHK( mpi_lset( X, 0 ) );
1734
Paul Bakker39dfdac2012-02-12 17:17:27 +00001735 MPI_CHK( f_rng( p_rng, (unsigned char *) X->p, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001736
1737cleanup:
1738 return( ret );
1739}
1740
Paul Bakker5121ce52009-01-03 21:22:43 +00001741/*
1742 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1743 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001744int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001745{
1746 int ret;
1747 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1748
1749 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001750 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001751
Paul Bakker6c591fa2011-05-05 11:49:20 +00001752 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1753 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1754 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001755
1756 MPI_CHK( mpi_gcd( &G, A, N ) );
1757
1758 if( mpi_cmp_int( &G, 1 ) != 0 )
1759 {
Paul Bakker40e46942009-01-03 21:51:57 +00001760 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001761 goto cleanup;
1762 }
1763
1764 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1765 MPI_CHK( mpi_copy( &TU, &TA ) );
1766 MPI_CHK( mpi_copy( &TB, N ) );
1767 MPI_CHK( mpi_copy( &TV, N ) );
1768
1769 MPI_CHK( mpi_lset( &U1, 1 ) );
1770 MPI_CHK( mpi_lset( &U2, 0 ) );
1771 MPI_CHK( mpi_lset( &V1, 0 ) );
1772 MPI_CHK( mpi_lset( &V2, 1 ) );
1773
1774 do
1775 {
1776 while( ( TU.p[0] & 1 ) == 0 )
1777 {
1778 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1779
1780 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1781 {
1782 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1783 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1784 }
1785
1786 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1787 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1788 }
1789
1790 while( ( TV.p[0] & 1 ) == 0 )
1791 {
1792 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1793
1794 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1795 {
1796 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1797 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1798 }
1799
1800 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1801 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1802 }
1803
1804 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1805 {
1806 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1807 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1808 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1809 }
1810 else
1811 {
1812 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1813 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1814 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1815 }
1816 }
1817 while( mpi_cmp_int( &TU, 0 ) != 0 );
1818
1819 while( mpi_cmp_int( &V1, 0 ) < 0 )
1820 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1821
1822 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1823 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1824
1825 MPI_CHK( mpi_copy( X, &V1 ) );
1826
1827cleanup:
1828
Paul Bakker6c591fa2011-05-05 11:49:20 +00001829 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1830 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1831 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001832
1833 return( ret );
1834}
1835
Paul Bakkerd9374b02012-11-02 11:02:58 +00001836#if defined(POLARSSL_GENPRIME)
1837
Paul Bakker5121ce52009-01-03 21:22:43 +00001838static const int small_prime[] =
1839{
1840 3, 5, 7, 11, 13, 17, 19, 23,
1841 29, 31, 37, 41, 43, 47, 53, 59,
1842 61, 67, 71, 73, 79, 83, 89, 97,
1843 101, 103, 107, 109, 113, 127, 131, 137,
1844 139, 149, 151, 157, 163, 167, 173, 179,
1845 181, 191, 193, 197, 199, 211, 223, 227,
1846 229, 233, 239, 241, 251, 257, 263, 269,
1847 271, 277, 281, 283, 293, 307, 311, 313,
1848 317, 331, 337, 347, 349, 353, 359, 367,
1849 373, 379, 383, 389, 397, 401, 409, 419,
1850 421, 431, 433, 439, 443, 449, 457, 461,
1851 463, 467, 479, 487, 491, 499, 503, 509,
1852 521, 523, 541, 547, 557, 563, 569, 571,
1853 577, 587, 593, 599, 601, 607, 613, 617,
1854 619, 631, 641, 643, 647, 653, 659, 661,
1855 673, 677, 683, 691, 701, 709, 719, 727,
1856 733, 739, 743, 751, 757, 761, 769, 773,
1857 787, 797, 809, 811, 821, 823, 827, 829,
1858 839, 853, 857, 859, 863, 877, 881, 883,
1859 887, 907, 911, 919, 929, 937, 941, 947,
1860 953, 967, 971, 977, 983, 991, 997, -103
1861};
1862
1863/*
1864 * Miller-Rabin primality test (HAC 4.24)
1865 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001866int mpi_is_prime( mpi *X,
1867 int (*f_rng)(void *, unsigned char *, size_t),
1868 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001869{
Paul Bakker23986e52011-04-24 08:57:21 +00001870 int ret, xs;
1871 size_t i, j, n, s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001872 mpi W, R, T, A, RR;
Paul Bakker5121ce52009-01-03 21:22:43 +00001873
Paul Bakker48eab262009-06-25 21:25:49 +00001874 if( mpi_cmp_int( X, 0 ) == 0 ||
1875 mpi_cmp_int( X, 1 ) == 0 )
1876 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1877
1878 if( mpi_cmp_int( X, 2 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001879 return( 0 );
1880
Paul Bakker6c591fa2011-05-05 11:49:20 +00001881 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
1882 mpi_init( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001883
1884 xs = X->s; X->s = 1;
1885
1886 /*
1887 * test trivial factors first
1888 */
1889 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001890 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001891
1892 for( i = 0; small_prime[i] > 0; i++ )
1893 {
Paul Bakkera755ca12011-04-24 09:11:17 +00001894 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001895
1896 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
1897 return( 0 );
1898
1899 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1900
1901 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001902 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001903 }
1904
1905 /*
1906 * W = |X| - 1
1907 * R = W >> lsb( W )
1908 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001909 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001910 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001911 MPI_CHK( mpi_copy( &R, &W ) );
1912 MPI_CHK( mpi_shift_r( &R, s ) );
1913
1914 i = mpi_msb( X );
1915 /*
1916 * HAC, table 4.4
1917 */
1918 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1919 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1920 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1921
1922 for( i = 0; i < n; i++ )
1923 {
1924 /*
1925 * pick a random A, 1 < A < |X| - 1
1926 */
Paul Bakker901c6562012-04-20 13:25:38 +00001927 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001928
Paul Bakkerb94081b2011-01-05 15:53:06 +00001929 if( mpi_cmp_mpi( &A, &W ) >= 0 )
1930 {
1931 j = mpi_msb( &A ) - mpi_msb( &W );
1932 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1933 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001934 A.p[0] |= 3;
1935
1936 /*
1937 * A = A^R mod |X|
1938 */
1939 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1940
1941 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1942 mpi_cmp_int( &A, 1 ) == 0 )
1943 continue;
1944
1945 j = 1;
1946 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1947 {
1948 /*
1949 * A = A * A mod |X|
1950 */
1951 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1952 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1953
1954 if( mpi_cmp_int( &A, 1 ) == 0 )
1955 break;
1956
1957 j++;
1958 }
1959
1960 /*
1961 * not prime if A != |X| - 1 or A == 1
1962 */
1963 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1964 mpi_cmp_int( &A, 1 ) == 0 )
1965 {
Paul Bakker40e46942009-01-03 21:51:57 +00001966 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001967 break;
1968 }
1969 }
1970
1971cleanup:
1972
1973 X->s = xs;
1974
Paul Bakker6c591fa2011-05-05 11:49:20 +00001975 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
1976 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001977
1978 return( ret );
1979}
1980
1981/*
1982 * Prime number generation
1983 */
Paul Bakker23986e52011-04-24 08:57:21 +00001984int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001985 int (*f_rng)(void *, unsigned char *, size_t),
1986 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001987{
Paul Bakker23986e52011-04-24 08:57:21 +00001988 int ret;
1989 size_t k, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001990 mpi Y;
1991
Paul Bakkerfe3256e2011-11-25 12:11:43 +00001992 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00001993 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001994
Paul Bakker6c591fa2011-05-05 11:49:20 +00001995 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001996
1997 n = BITS_TO_LIMBS( nbits );
1998
Paul Bakker901c6562012-04-20 13:25:38 +00001999 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002000
2001 k = mpi_msb( X );
2002 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
2003 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
2004
2005 X->p[0] |= 3;
2006
2007 if( dh_flag == 0 )
2008 {
2009 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
2010 {
Paul Bakker40e46942009-01-03 21:51:57 +00002011 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002012 goto cleanup;
2013
2014 MPI_CHK( mpi_add_int( X, X, 2 ) );
2015 }
2016 }
2017 else
2018 {
2019 MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
2020 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2021
2022 while( 1 )
2023 {
2024 if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
2025 {
2026 if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
2027 break;
2028
Paul Bakker40e46942009-01-03 21:51:57 +00002029 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002030 goto cleanup;
2031 }
2032
Paul Bakker40e46942009-01-03 21:51:57 +00002033 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002034 goto cleanup;
2035
2036 MPI_CHK( mpi_add_int( &Y, X, 1 ) );
2037 MPI_CHK( mpi_add_int( X, X, 2 ) );
2038 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2039 }
2040 }
2041
2042cleanup:
2043
Paul Bakker6c591fa2011-05-05 11:49:20 +00002044 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002045
2046 return( ret );
2047}
2048
Manuel Pégourié-Gonnarddf0142b2013-08-22 18:29:07 +02002049#endif /* POLARSSL_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002050
Paul Bakker40e46942009-01-03 21:51:57 +00002051#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002052
Paul Bakker23986e52011-04-24 08:57:21 +00002053#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002054
2055static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2056{
2057 { 693, 609, 21 },
2058 { 1764, 868, 28 },
2059 { 768454923, 542167814, 1 }
2060};
2061
Paul Bakker5121ce52009-01-03 21:22:43 +00002062/*
2063 * Checkup routine
2064 */
2065int mpi_self_test( int verbose )
2066{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002067 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002068 mpi A, E, N, X, Y, U, V;
2069
Paul Bakker6c591fa2011-05-05 11:49:20 +00002070 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2071 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002072
2073 MPI_CHK( mpi_read_string( &A, 16,
2074 "EFE021C2645FD1DC586E69184AF4A31E" \
2075 "D5F53E93B5F123FA41680867BA110131" \
2076 "944FE7952E2517337780CB0DB80E61AA" \
2077 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2078
2079 MPI_CHK( mpi_read_string( &E, 16,
2080 "B2E7EFD37075B9F03FF989C7C5051C20" \
2081 "34D2A323810251127E7BF8625A4F49A5" \
2082 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2083 "5B5C25763222FEFCCFC38B832366C29E" ) );
2084
2085 MPI_CHK( mpi_read_string( &N, 16,
2086 "0066A198186C18C10B2F5ED9B522752A" \
2087 "9830B69916E535C8F047518A889A43A5" \
2088 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2089
2090 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2091
2092 MPI_CHK( mpi_read_string( &U, 16,
2093 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2094 "9E857EA95A03512E2BAE7391688D264A" \
2095 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2096 "8001B72E848A38CAE1C65F78E56ABDEF" \
2097 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2098 "ECF677152EF804370C1A305CAF3B5BF1" \
2099 "30879B56C61DE584A0F53A2447A51E" ) );
2100
2101 if( verbose != 0 )
2102 printf( " MPI test #1 (mul_mpi): " );
2103
2104 if( mpi_cmp_mpi( &X, &U ) != 0 )
2105 {
2106 if( verbose != 0 )
2107 printf( "failed\n" );
2108
2109 return( 1 );
2110 }
2111
2112 if( verbose != 0 )
2113 printf( "passed\n" );
2114
2115 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2116
2117 MPI_CHK( mpi_read_string( &U, 16,
2118 "256567336059E52CAE22925474705F39A94" ) );
2119
2120 MPI_CHK( mpi_read_string( &V, 16,
2121 "6613F26162223DF488E9CD48CC132C7A" \
2122 "0AC93C701B001B092E4E5B9F73BCD27B" \
2123 "9EE50D0657C77F374E903CDFA4C642" ) );
2124
2125 if( verbose != 0 )
2126 printf( " MPI test #2 (div_mpi): " );
2127
2128 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2129 mpi_cmp_mpi( &Y, &V ) != 0 )
2130 {
2131 if( verbose != 0 )
2132 printf( "failed\n" );
2133
2134 return( 1 );
2135 }
2136
2137 if( verbose != 0 )
2138 printf( "passed\n" );
2139
2140 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2141
2142 MPI_CHK( mpi_read_string( &U, 16,
2143 "36E139AEA55215609D2816998ED020BB" \
2144 "BD96C37890F65171D948E9BC7CBAA4D9" \
2145 "325D24D6A3C12710F10A09FA08AB87" ) );
2146
2147 if( verbose != 0 )
2148 printf( " MPI test #3 (exp_mod): " );
2149
2150 if( mpi_cmp_mpi( &X, &U ) != 0 )
2151 {
2152 if( verbose != 0 )
2153 printf( "failed\n" );
2154
2155 return( 1 );
2156 }
2157
2158 if( verbose != 0 )
2159 printf( "passed\n" );
2160
2161 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2162
2163 MPI_CHK( mpi_read_string( &U, 16,
2164 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2165 "C3DBA76456363A10869622EAC2DD84EC" \
2166 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2167
2168 if( verbose != 0 )
2169 printf( " MPI test #4 (inv_mod): " );
2170
2171 if( mpi_cmp_mpi( &X, &U ) != 0 )
2172 {
2173 if( verbose != 0 )
2174 printf( "failed\n" );
2175
2176 return( 1 );
2177 }
2178
2179 if( verbose != 0 )
2180 printf( "passed\n" );
2181
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002182 if( verbose != 0 )
2183 printf( " MPI test #5 (simple gcd): " );
2184
2185 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2186 {
2187 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002188 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002189
Paul Bakker23986e52011-04-24 08:57:21 +00002190 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002191
Paul Bakker23986e52011-04-24 08:57:21 +00002192 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2193 {
2194 if( verbose != 0 )
2195 printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002196
Paul Bakker23986e52011-04-24 08:57:21 +00002197 return( 1 );
2198 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002199 }
2200
2201 if( verbose != 0 )
2202 printf( "passed\n" );
2203
Paul Bakker5121ce52009-01-03 21:22:43 +00002204cleanup:
2205
2206 if( ret != 0 && verbose != 0 )
2207 printf( "Unexpected error, return code = %08X\n", ret );
2208
Paul Bakker6c591fa2011-05-05 11:49:20 +00002209 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2210 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002211
2212 if( verbose != 0 )
2213 printf( "\n" );
2214
2215 return( ret );
2216}
2217
2218#endif
2219
2220#endif