blob: 55f7463a95f5a3364580ba0b74a4460ee56cbe89 [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/*
208 * Set value from integer
209 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000210int mpi_lset( mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000211{
212 int ret;
213
214 MPI_CHK( mpi_grow( X, 1 ) );
215 memset( X->p, 0, X->n * ciL );
216
217 X->p[0] = ( z < 0 ) ? -z : z;
218 X->s = ( z < 0 ) ? -1 : 1;
219
220cleanup:
221
222 return( ret );
223}
224
225/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000226 * Get a specific bit
227 */
Paul Bakker6b906e52012-05-08 12:01:43 +0000228int mpi_get_bit( const mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000229{
230 if( X->n * biL <= pos )
231 return( 0 );
232
233 return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
234}
235
236/*
237 * Set a bit to a specific value of 0 or 1
238 */
239int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
240{
241 int ret = 0;
242 size_t off = pos / biL;
243 size_t idx = pos % biL;
244
245 if( val != 0 && val != 1 )
246 return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
247
248 if( X->n * biL <= pos )
249 {
250 if( val == 0 )
251 return ( 0 );
252
253 MPI_CHK( mpi_grow( X, off + 1 ) );
254 }
255
256 X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
257
258cleanup:
259
260 return( ret );
261}
262
263/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000264 * Return the number of least significant bits
265 */
Paul Bakker23986e52011-04-24 08:57:21 +0000266size_t mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000267{
Paul Bakker23986e52011-04-24 08:57:21 +0000268 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000269
270 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000271 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000272 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
273 return( count );
274
275 return( 0 );
276}
277
278/*
279 * Return the number of most significant bits
280 */
Paul Bakker23986e52011-04-24 08:57:21 +0000281size_t mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000282{
Paul Bakker23986e52011-04-24 08:57:21 +0000283 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000284
285 for( i = X->n - 1; i > 0; i-- )
286 if( X->p[i] != 0 )
287 break;
288
Paul Bakker23986e52011-04-24 08:57:21 +0000289 for( j = biL; j > 0; j-- )
290 if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000291 break;
292
Paul Bakker23986e52011-04-24 08:57:21 +0000293 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000294}
295
296/*
297 * Return the total size in bytes
298 */
Paul Bakker23986e52011-04-24 08:57:21 +0000299size_t mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000300{
301 return( ( mpi_msb( X ) + 7 ) >> 3 );
302}
303
304/*
305 * Convert an ASCII character to digit value
306 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000307static int mpi_get_digit( t_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000308{
309 *d = 255;
310
311 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
312 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
313 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
314
Paul Bakkera755ca12011-04-24 09:11:17 +0000315 if( *d >= (t_uint) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000316 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000317
318 return( 0 );
319}
320
321/*
322 * Import from an ASCII string
323 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000324int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000325{
Paul Bakker23986e52011-04-24 08:57:21 +0000326 int ret;
327 size_t i, j, slen, n;
Paul Bakkera755ca12011-04-24 09:11:17 +0000328 t_uint d;
Paul Bakker5121ce52009-01-03 21:22:43 +0000329 mpi T;
330
331 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000332 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000333
Paul Bakker6c591fa2011-05-05 11:49:20 +0000334 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000335
Paul Bakkerff60ee62010-03-16 21:09:09 +0000336 slen = strlen( s );
337
Paul Bakker5121ce52009-01-03 21:22:43 +0000338 if( radix == 16 )
339 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000340 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000341
342 MPI_CHK( mpi_grow( X, n ) );
343 MPI_CHK( mpi_lset( X, 0 ) );
344
Paul Bakker23986e52011-04-24 08:57:21 +0000345 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000346 {
Paul Bakker23986e52011-04-24 08:57:21 +0000347 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000348 {
349 X->s = -1;
350 break;
351 }
352
Paul Bakker23986e52011-04-24 08:57:21 +0000353 MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000354 X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
355 }
356 }
357 else
358 {
359 MPI_CHK( mpi_lset( X, 0 ) );
360
Paul Bakkerff60ee62010-03-16 21:09:09 +0000361 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000362 {
363 if( i == 0 && s[i] == '-' )
364 {
365 X->s = -1;
366 continue;
367 }
368
369 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
370 MPI_CHK( mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000371
372 if( X->s == 1 )
373 {
374 MPI_CHK( mpi_add_int( X, &T, d ) );
375 }
376 else
377 {
378 MPI_CHK( mpi_sub_int( X, &T, d ) );
379 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000380 }
381 }
382
383cleanup:
384
Paul Bakker6c591fa2011-05-05 11:49:20 +0000385 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000386
387 return( ret );
388}
389
390/*
391 * Helper to write the digits high-order first
392 */
393static int mpi_write_hlp( mpi *X, int radix, char **p )
394{
395 int ret;
Paul Bakkera755ca12011-04-24 09:11:17 +0000396 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000397
398 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000399 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000400
401 MPI_CHK( mpi_mod_int( &r, X, radix ) );
402 MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
403
404 if( mpi_cmp_int( X, 0 ) != 0 )
405 MPI_CHK( mpi_write_hlp( X, radix, p ) );
406
407 if( r < 10 )
408 *(*p)++ = (char)( r + 0x30 );
409 else
410 *(*p)++ = (char)( r + 0x37 );
411
412cleanup:
413
414 return( ret );
415}
416
417/*
418 * Export into an ASCII string
419 */
Paul Bakker23986e52011-04-24 08:57:21 +0000420int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000421{
Paul Bakker23986e52011-04-24 08:57:21 +0000422 int ret = 0;
423 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000424 char *p;
425 mpi T;
426
427 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000428 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000429
430 n = mpi_msb( X );
431 if( radix >= 4 ) n >>= 1;
432 if( radix >= 16 ) n >>= 1;
433 n += 3;
434
435 if( *slen < n )
436 {
437 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000438 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000439 }
440
441 p = s;
Paul Bakker6c591fa2011-05-05 11:49:20 +0000442 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000443
444 if( X->s == -1 )
445 *p++ = '-';
446
447 if( radix == 16 )
448 {
Paul Bakker23986e52011-04-24 08:57:21 +0000449 int c;
450 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000451
Paul Bakker23986e52011-04-24 08:57:21 +0000452 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000453 {
Paul Bakker23986e52011-04-24 08:57:21 +0000454 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000455 {
Paul Bakker23986e52011-04-24 08:57:21 +0000456 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000457
Paul Bakker23986e52011-04-24 08:57:21 +0000458 if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000459 continue;
460
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000461 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000462 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000463 k = 1;
464 }
465 }
466 }
467 else
468 {
469 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000470
471 if( T.s == -1 )
472 T.s = 1;
473
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
475 }
476
477 *p++ = '\0';
478 *slen = p - s;
479
480cleanup:
481
Paul Bakker6c591fa2011-05-05 11:49:20 +0000482 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
484 return( ret );
485}
486
Paul Bakker335db3f2011-04-25 15:28:35 +0000487#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000488/*
489 * Read X from an opened file
490 */
491int mpi_read_file( mpi *X, int radix, FILE *fin )
492{
Paul Bakkera755ca12011-04-24 09:11:17 +0000493 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000494 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000495 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000496 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000497 * Buffer should have space for (short) label and decimal formatted MPI,
498 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000499 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000500 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000501
502 memset( s, 0, sizeof( s ) );
503 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000504 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000505
506 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000507 if( slen == sizeof( s ) - 2 )
508 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
509
Paul Bakker5121ce52009-01-03 21:22:43 +0000510 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
511 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
512
513 p = s + slen;
514 while( --p >= s )
515 if( mpi_get_digit( &d, radix, *p ) != 0 )
516 break;
517
518 return( mpi_read_string( X, radix, p + 1 ) );
519}
520
521/*
522 * Write X into an opened file (or stdout if fout == NULL)
523 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000524int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000525{
Paul Bakker23986e52011-04-24 08:57:21 +0000526 int ret;
527 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000528 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000529 * Buffer should have space for (short) label and decimal formatted MPI,
530 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000531 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000532 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000533
534 n = sizeof( s );
535 memset( s, 0, n );
536 n -= 2;
537
Paul Bakker23986e52011-04-24 08:57:21 +0000538 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
540 if( p == NULL ) p = "";
541
542 plen = strlen( p );
543 slen = strlen( s );
544 s[slen++] = '\r';
545 s[slen++] = '\n';
546
547 if( fout != NULL )
548 {
549 if( fwrite( p, 1, plen, fout ) != plen ||
550 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000551 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000552 }
553 else
554 printf( "%s%s", p, s );
555
556cleanup:
557
558 return( ret );
559}
Paul Bakker335db3f2011-04-25 15:28:35 +0000560#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000561
562/*
563 * Import X from unsigned binary data, big endian
564 */
Paul Bakker23986e52011-04-24 08:57:21 +0000565int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000566{
Paul Bakker23986e52011-04-24 08:57:21 +0000567 int ret;
568 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000569
570 for( n = 0; n < buflen; n++ )
571 if( buf[n] != 0 )
572 break;
573
574 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
575 MPI_CHK( mpi_lset( X, 0 ) );
576
Paul Bakker23986e52011-04-24 08:57:21 +0000577 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000578 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000579
580cleanup:
581
582 return( ret );
583}
584
585/*
586 * Export X into unsigned binary data, big endian
587 */
Paul Bakker23986e52011-04-24 08:57:21 +0000588int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000589{
Paul Bakker23986e52011-04-24 08:57:21 +0000590 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000591
592 n = mpi_size( X );
593
594 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000595 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000596
597 memset( buf, 0, buflen );
598
599 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
600 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
601
602 return( 0 );
603}
604
605/*
606 * Left-shift: X <<= count
607 */
Paul Bakker23986e52011-04-24 08:57:21 +0000608int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000609{
Paul Bakker23986e52011-04-24 08:57:21 +0000610 int ret;
611 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000612 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000613
614 v0 = count / (biL );
615 t1 = count & (biL - 1);
616
617 i = mpi_msb( X ) + count;
618
Paul Bakkerf9688572011-05-05 10:00:45 +0000619 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000620 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
621
622 ret = 0;
623
624 /*
625 * shift by count / limb_size
626 */
627 if( v0 > 0 )
628 {
Paul Bakker23986e52011-04-24 08:57:21 +0000629 for( i = X->n; i > v0; i-- )
630 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000631
Paul Bakker23986e52011-04-24 08:57:21 +0000632 for( ; i > 0; i-- )
633 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000634 }
635
636 /*
637 * shift by count % limb_size
638 */
639 if( t1 > 0 )
640 {
641 for( i = v0; i < X->n; i++ )
642 {
643 r1 = X->p[i] >> (biL - t1);
644 X->p[i] <<= t1;
645 X->p[i] |= r0;
646 r0 = r1;
647 }
648 }
649
650cleanup:
651
652 return( ret );
653}
654
655/*
656 * Right-shift: X >>= count
657 */
Paul Bakker23986e52011-04-24 08:57:21 +0000658int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000659{
Paul Bakker23986e52011-04-24 08:57:21 +0000660 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000661 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000662
663 v0 = count / biL;
664 v1 = count & (biL - 1);
665
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100666 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
667 return mpi_lset( X, 0 );
668
Paul Bakker5121ce52009-01-03 21:22:43 +0000669 /*
670 * shift by count / limb_size
671 */
672 if( v0 > 0 )
673 {
674 for( i = 0; i < X->n - v0; i++ )
675 X->p[i] = X->p[i + v0];
676
677 for( ; i < X->n; i++ )
678 X->p[i] = 0;
679 }
680
681 /*
682 * shift by count % limb_size
683 */
684 if( v1 > 0 )
685 {
Paul Bakker23986e52011-04-24 08:57:21 +0000686 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000687 {
Paul Bakker23986e52011-04-24 08:57:21 +0000688 r1 = X->p[i - 1] << (biL - v1);
689 X->p[i - 1] >>= v1;
690 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000691 r0 = r1;
692 }
693 }
694
695 return( 0 );
696}
697
698/*
699 * Compare unsigned values
700 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000701int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000702{
Paul Bakker23986e52011-04-24 08:57:21 +0000703 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000704
Paul Bakker23986e52011-04-24 08:57:21 +0000705 for( i = X->n; i > 0; i-- )
706 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000707 break;
708
Paul Bakker23986e52011-04-24 08:57:21 +0000709 for( j = Y->n; j > 0; j-- )
710 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000711 break;
712
Paul Bakker23986e52011-04-24 08:57:21 +0000713 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000714 return( 0 );
715
716 if( i > j ) return( 1 );
717 if( j > i ) return( -1 );
718
Paul Bakker23986e52011-04-24 08:57:21 +0000719 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000720 {
Paul Bakker23986e52011-04-24 08:57:21 +0000721 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
722 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000723 }
724
725 return( 0 );
726}
727
728/*
729 * Compare signed values
730 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000731int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000732{
Paul Bakker23986e52011-04-24 08:57:21 +0000733 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000734
Paul Bakker23986e52011-04-24 08:57:21 +0000735 for( i = X->n; i > 0; i-- )
736 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000737 break;
738
Paul Bakker23986e52011-04-24 08:57:21 +0000739 for( j = Y->n; j > 0; j-- )
740 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000741 break;
742
Paul Bakker23986e52011-04-24 08:57:21 +0000743 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000744 return( 0 );
745
746 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000747 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000748
749 if( X->s > 0 && Y->s < 0 ) return( 1 );
750 if( Y->s > 0 && X->s < 0 ) return( -1 );
751
Paul Bakker23986e52011-04-24 08:57:21 +0000752 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000753 {
Paul Bakker23986e52011-04-24 08:57:21 +0000754 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
755 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000756 }
757
758 return( 0 );
759}
760
761/*
762 * Compare signed values
763 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000764int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000765{
766 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000767 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000768
769 *p = ( z < 0 ) ? -z : z;
770 Y.s = ( z < 0 ) ? -1 : 1;
771 Y.n = 1;
772 Y.p = p;
773
774 return( mpi_cmp_mpi( X, &Y ) );
775}
776
777/*
778 * Unsigned addition: X = |A| + |B| (HAC 14.7)
779 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000780int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000781{
Paul Bakker23986e52011-04-24 08:57:21 +0000782 int ret;
783 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000784 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000785
786 if( X == B )
787 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000788 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000789 }
790
791 if( X != A )
792 MPI_CHK( mpi_copy( X, A ) );
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000793
794 /*
795 * X should always be positive as a result of unsigned additions.
796 */
797 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000798
Paul Bakker23986e52011-04-24 08:57:21 +0000799 for( j = B->n; j > 0; j-- )
800 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000801 break;
802
Paul Bakker23986e52011-04-24 08:57:21 +0000803 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000804
805 o = B->p; p = X->p; c = 0;
806
Paul Bakker23986e52011-04-24 08:57:21 +0000807 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000808 {
809 *p += c; c = ( *p < c );
810 *p += *o; c += ( *p < *o );
811 }
812
813 while( c != 0 )
814 {
815 if( i >= X->n )
816 {
817 MPI_CHK( mpi_grow( X, i + 1 ) );
818 p = X->p + i;
819 }
820
Paul Bakker2d319fd2012-09-16 21:34:26 +0000821 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000822 }
823
824cleanup:
825
826 return( ret );
827}
828
829/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100830 * Helper for mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000831 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000832static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000833{
Paul Bakker23986e52011-04-24 08:57:21 +0000834 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000835 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000836
837 for( i = c = 0; i < n; i++, s++, d++ )
838 {
839 z = ( *d < c ); *d -= c;
840 c = ( *d < *s ) + z; *d -= *s;
841 }
842
843 while( c != 0 )
844 {
845 z = ( *d < c ); *d -= c;
846 c = z; i++; d++;
847 }
848}
849
850/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100851 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000852 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000853int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000854{
855 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000856 int ret;
857 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000858
859 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000860 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000861
Paul Bakker6c591fa2011-05-05 11:49:20 +0000862 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000863
864 if( X == B )
865 {
866 MPI_CHK( mpi_copy( &TB, B ) );
867 B = &TB;
868 }
869
870 if( X != A )
871 MPI_CHK( mpi_copy( X, A ) );
872
Paul Bakker1ef7a532009-06-20 10:50:55 +0000873 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100874 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000875 */
876 X->s = 1;
877
Paul Bakker5121ce52009-01-03 21:22:43 +0000878 ret = 0;
879
Paul Bakker23986e52011-04-24 08:57:21 +0000880 for( n = B->n; n > 0; n-- )
881 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000882 break;
883
Paul Bakker23986e52011-04-24 08:57:21 +0000884 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000885
886cleanup:
887
Paul Bakker6c591fa2011-05-05 11:49:20 +0000888 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000889
890 return( ret );
891}
892
893/*
894 * Signed addition: X = A + B
895 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000896int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000897{
898 int ret, s = A->s;
899
900 if( A->s * B->s < 0 )
901 {
902 if( mpi_cmp_abs( A, B ) >= 0 )
903 {
904 MPI_CHK( mpi_sub_abs( X, A, B ) );
905 X->s = s;
906 }
907 else
908 {
909 MPI_CHK( mpi_sub_abs( X, B, A ) );
910 X->s = -s;
911 }
912 }
913 else
914 {
915 MPI_CHK( mpi_add_abs( X, A, B ) );
916 X->s = s;
917 }
918
919cleanup:
920
921 return( ret );
922}
923
924/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100925 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +0000926 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000927int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000928{
929 int ret, s = A->s;
930
931 if( A->s * B->s > 0 )
932 {
933 if( mpi_cmp_abs( A, B ) >= 0 )
934 {
935 MPI_CHK( mpi_sub_abs( X, A, B ) );
936 X->s = s;
937 }
938 else
939 {
940 MPI_CHK( mpi_sub_abs( X, B, A ) );
941 X->s = -s;
942 }
943 }
944 else
945 {
946 MPI_CHK( mpi_add_abs( X, A, B ) );
947 X->s = s;
948 }
949
950cleanup:
951
952 return( ret );
953}
954
955/*
956 * Signed addition: X = A + b
957 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000958int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000959{
960 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000961 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000962
963 p[0] = ( b < 0 ) ? -b : b;
964 _B.s = ( b < 0 ) ? -1 : 1;
965 _B.n = 1;
966 _B.p = p;
967
968 return( mpi_add_mpi( X, A, &_B ) );
969}
970
971/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100972 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +0000973 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000974int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000975{
976 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000977 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000978
979 p[0] = ( b < 0 ) ? -b : b;
980 _B.s = ( b < 0 ) ? -1 : 1;
981 _B.n = 1;
982 _B.p = p;
983
984 return( mpi_sub_mpi( X, A, &_B ) );
985}
986
987/*
988 * Helper for mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +0200989 */
990static
991#if defined(__APPLE__) && defined(__arm__)
992/*
993 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
994 * appears to need this to prevent bad ARM code generation at -O3.
995 */
996__attribute__ ((noinline))
997#endif
998void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000999{
Paul Bakkera755ca12011-04-24 09:11:17 +00001000 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001001
1002#if defined(MULADDC_HUIT)
1003 for( ; i >= 8; i -= 8 )
1004 {
1005 MULADDC_INIT
1006 MULADDC_HUIT
1007 MULADDC_STOP
1008 }
1009
1010 for( ; i > 0; i-- )
1011 {
1012 MULADDC_INIT
1013 MULADDC_CORE
1014 MULADDC_STOP
1015 }
1016#else
1017 for( ; i >= 16; i -= 16 )
1018 {
1019 MULADDC_INIT
1020 MULADDC_CORE MULADDC_CORE
1021 MULADDC_CORE MULADDC_CORE
1022 MULADDC_CORE MULADDC_CORE
1023 MULADDC_CORE MULADDC_CORE
1024
1025 MULADDC_CORE MULADDC_CORE
1026 MULADDC_CORE MULADDC_CORE
1027 MULADDC_CORE MULADDC_CORE
1028 MULADDC_CORE MULADDC_CORE
1029 MULADDC_STOP
1030 }
1031
1032 for( ; i >= 8; i -= 8 )
1033 {
1034 MULADDC_INIT
1035 MULADDC_CORE MULADDC_CORE
1036 MULADDC_CORE MULADDC_CORE
1037
1038 MULADDC_CORE MULADDC_CORE
1039 MULADDC_CORE MULADDC_CORE
1040 MULADDC_STOP
1041 }
1042
1043 for( ; i > 0; i-- )
1044 {
1045 MULADDC_INIT
1046 MULADDC_CORE
1047 MULADDC_STOP
1048 }
1049#endif
1050
1051 t++;
1052
1053 do {
1054 *d += c; c = ( *d < c ); d++;
1055 }
1056 while( c != 0 );
1057}
1058
1059/*
1060 * Baseline multiplication: X = A * B (HAC 14.12)
1061 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001062int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001063{
Paul Bakker23986e52011-04-24 08:57:21 +00001064 int ret;
1065 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001066 mpi TA, TB;
1067
Paul Bakker6c591fa2011-05-05 11:49:20 +00001068 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001069
1070 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1071 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1072
Paul Bakker23986e52011-04-24 08:57:21 +00001073 for( i = A->n; i > 0; i-- )
1074 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001075 break;
1076
Paul Bakker23986e52011-04-24 08:57:21 +00001077 for( j = B->n; j > 0; j-- )
1078 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001079 break;
1080
Paul Bakker23986e52011-04-24 08:57:21 +00001081 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001082 MPI_CHK( mpi_lset( X, 0 ) );
1083
Paul Bakker23986e52011-04-24 08:57:21 +00001084 for( i++; j > 0; j-- )
1085 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001086
1087 X->s = A->s * B->s;
1088
1089cleanup:
1090
Paul Bakker6c591fa2011-05-05 11:49:20 +00001091 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001092
1093 return( ret );
1094}
1095
1096/*
1097 * Baseline multiplication: X = A * b
1098 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001099int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001100{
1101 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001102 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001103
1104 _B.s = 1;
1105 _B.n = 1;
1106 _B.p = p;
1107 p[0] = b;
1108
1109 return( mpi_mul_mpi( X, A, &_B ) );
1110}
1111
1112/*
1113 * Division by mpi: A = Q * B + R (HAC 14.20)
1114 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001115int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001116{
Paul Bakker23986e52011-04-24 08:57:21 +00001117 int ret;
1118 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001119 mpi X, Y, Z, T1, T2;
1120
1121 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001122 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001123
Paul Bakker6c591fa2011-05-05 11:49:20 +00001124 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1125 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001126
1127 if( mpi_cmp_abs( A, B ) < 0 )
1128 {
1129 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1130 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1131 return( 0 );
1132 }
1133
1134 MPI_CHK( mpi_copy( &X, A ) );
1135 MPI_CHK( mpi_copy( &Y, B ) );
1136 X.s = Y.s = 1;
1137
1138 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1139 MPI_CHK( mpi_lset( &Z, 0 ) );
1140 MPI_CHK( mpi_grow( &T1, 2 ) );
1141 MPI_CHK( mpi_grow( &T2, 3 ) );
1142
1143 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001144 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001145 {
1146 k = biL - 1 - k;
1147 MPI_CHK( mpi_shift_l( &X, k ) );
1148 MPI_CHK( mpi_shift_l( &Y, k ) );
1149 }
1150 else k = 0;
1151
1152 n = X.n - 1;
1153 t = Y.n - 1;
Paul Bakkerc110d022012-10-19 12:15:08 +00001154 MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001155
1156 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1157 {
1158 Z.p[n - t]++;
1159 mpi_sub_mpi( &X, &X, &Y );
1160 }
1161 mpi_shift_r( &Y, biL * (n - t) );
1162
1163 for( i = n; i > t ; i-- )
1164 {
1165 if( X.p[i] >= Y.p[t] )
1166 Z.p[i - t - 1] = ~0;
1167 else
1168 {
Paul Bakker62261d62012-10-02 12:19:31 +00001169#if defined(POLARSSL_HAVE_UDBL)
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001170 t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001171
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001172 r = (t_udbl) X.p[i] << biL;
1173 r |= (t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001174 r /= Y.p[t];
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001175 if( r > ((t_udbl) 1 << biL) - 1)
1176 r = ((t_udbl) 1 << biL) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001177
Paul Bakkera755ca12011-04-24 09:11:17 +00001178 Z.p[i - t - 1] = (t_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001179#else
1180 /*
1181 * __udiv_qrnnd_c, from gmp/longlong.h
1182 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001183 t_uint q0, q1, r0, r1;
1184 t_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001185
1186 d = Y.p[t];
1187 d0 = ( d << biH ) >> biH;
1188 d1 = ( d >> biH );
1189
1190 q1 = X.p[i] / d1;
1191 r1 = X.p[i] - d1 * q1;
1192 r1 <<= biH;
1193 r1 |= ( X.p[i - 1] >> biH );
1194
1195 m = q1 * d0;
1196 if( r1 < m )
1197 {
1198 q1--, r1 += d;
1199 while( r1 >= d && r1 < m )
1200 q1--, r1 += d;
1201 }
1202 r1 -= m;
1203
1204 q0 = r1 / d1;
1205 r0 = r1 - d1 * q0;
1206 r0 <<= biH;
1207 r0 |= ( X.p[i - 1] << biH ) >> biH;
1208
1209 m = q0 * d0;
1210 if( r0 < m )
1211 {
1212 q0--, r0 += d;
1213 while( r0 >= d && r0 < m )
1214 q0--, r0 += d;
1215 }
1216 r0 -= m;
1217
1218 Z.p[i - t - 1] = ( q1 << biH ) | q0;
1219#endif
1220 }
1221
1222 Z.p[i - t - 1]++;
1223 do
1224 {
1225 Z.p[i - t - 1]--;
1226
1227 MPI_CHK( mpi_lset( &T1, 0 ) );
1228 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1229 T1.p[1] = Y.p[t];
1230 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1231
1232 MPI_CHK( mpi_lset( &T2, 0 ) );
1233 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1234 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1235 T2.p[2] = X.p[i];
1236 }
1237 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1238
1239 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1240 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1241 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1242
1243 if( mpi_cmp_int( &X, 0 ) < 0 )
1244 {
1245 MPI_CHK( mpi_copy( &T1, &Y ) );
1246 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1247 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1248 Z.p[i - t - 1]--;
1249 }
1250 }
1251
1252 if( Q != NULL )
1253 {
1254 mpi_copy( Q, &Z );
1255 Q->s = A->s * B->s;
1256 }
1257
1258 if( R != NULL )
1259 {
1260 mpi_shift_r( &X, k );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001261 X.s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001262 mpi_copy( R, &X );
1263
Paul Bakker5121ce52009-01-03 21:22:43 +00001264 if( mpi_cmp_int( R, 0 ) == 0 )
1265 R->s = 1;
1266 }
1267
1268cleanup:
1269
Paul Bakker6c591fa2011-05-05 11:49:20 +00001270 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1271 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001272
1273 return( ret );
1274}
1275
1276/*
1277 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001278 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001279int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001280{
1281 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001282 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001283
1284 p[0] = ( b < 0 ) ? -b : b;
1285 _B.s = ( b < 0 ) ? -1 : 1;
1286 _B.n = 1;
1287 _B.p = p;
1288
1289 return( mpi_div_mpi( Q, R, A, &_B ) );
1290}
1291
1292/*
1293 * Modulo: R = A mod B
1294 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001295int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001296{
1297 int ret;
1298
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001299 if( mpi_cmp_int( B, 0 ) < 0 )
1300 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1301
Paul Bakker5121ce52009-01-03 21:22:43 +00001302 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1303
1304 while( mpi_cmp_int( R, 0 ) < 0 )
1305 MPI_CHK( mpi_add_mpi( R, R, B ) );
1306
1307 while( mpi_cmp_mpi( R, B ) >= 0 )
1308 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1309
1310cleanup:
1311
1312 return( ret );
1313}
1314
1315/*
1316 * Modulo: r = A mod b
1317 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001318int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001319{
Paul Bakker23986e52011-04-24 08:57:21 +00001320 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001321 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001322
1323 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001324 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001325
1326 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001327 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001328
1329 /*
1330 * handle trivial cases
1331 */
1332 if( b == 1 )
1333 {
1334 *r = 0;
1335 return( 0 );
1336 }
1337
1338 if( b == 2 )
1339 {
1340 *r = A->p[0] & 1;
1341 return( 0 );
1342 }
1343
1344 /*
1345 * general case
1346 */
Paul Bakker23986e52011-04-24 08:57:21 +00001347 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001348 {
Paul Bakker23986e52011-04-24 08:57:21 +00001349 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001350 y = ( y << biH ) | ( x >> biH );
1351 z = y / b;
1352 y -= z * b;
1353
1354 x <<= biH;
1355 y = ( y << biH ) | ( x >> biH );
1356 z = y / b;
1357 y -= z * b;
1358 }
1359
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001360 /*
1361 * If A is negative, then the current y represents a negative value.
1362 * Flipping it to the positive side.
1363 */
1364 if( A->s < 0 && y != 0 )
1365 y = b - y;
1366
Paul Bakker5121ce52009-01-03 21:22:43 +00001367 *r = y;
1368
1369 return( 0 );
1370}
1371
1372/*
1373 * Fast Montgomery initialization (thanks to Tom St Denis)
1374 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001375static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001376{
Paul Bakkera755ca12011-04-24 09:11:17 +00001377 t_uint x, m0 = N->p[0];
Paul Bakker5121ce52009-01-03 21:22:43 +00001378
1379 x = m0;
1380 x += ( ( m0 + 2 ) & 4 ) << 1;
1381 x *= ( 2 - ( m0 * x ) );
1382
1383 if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
1384 if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
1385 if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
1386
1387 *mm = ~x + 1;
1388}
1389
1390/*
1391 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1392 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001393static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001394{
Paul Bakker23986e52011-04-24 08:57:21 +00001395 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001396 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001397
1398 memset( T->p, 0, T->n * ciL );
1399
1400 d = T->p;
1401 n = N->n;
1402 m = ( B->n < n ) ? B->n : n;
1403
1404 for( i = 0; i < n; i++ )
1405 {
1406 /*
1407 * T = (T + u0*B + u1*N) / 2^biL
1408 */
1409 u0 = A->p[i];
1410 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1411
1412 mpi_mul_hlp( m, B->p, d, u0 );
1413 mpi_mul_hlp( n, N->p, d, u1 );
1414
1415 *d++ = u0; d[n + 1] = 0;
1416 }
1417
1418 memcpy( A->p, d, (n + 1) * ciL );
1419
1420 if( mpi_cmp_abs( A, N ) >= 0 )
1421 mpi_sub_hlp( n, N->p, A->p );
1422 else
1423 /* prevent timing attacks */
1424 mpi_sub_hlp( n, A->p, T->p );
1425}
1426
1427/*
1428 * Montgomery reduction: A = A * R^-1 mod N
1429 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001430static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001431{
Paul Bakkera755ca12011-04-24 09:11:17 +00001432 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001433 mpi U;
1434
Paul Bakker8ddb6452013-02-27 14:56:33 +01001435 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001436 U.p = &z;
1437
1438 mpi_montmul( A, &U, N, mm, T );
1439}
1440
1441/*
1442 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1443 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001444int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001445{
Paul Bakker23986e52011-04-24 08:57:21 +00001446 int ret;
1447 size_t wbits, wsize, one = 1;
1448 size_t i, j, nblimbs;
1449 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001450 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001451 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1452 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001453
1454 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001455 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001456
Paul Bakkerf6198c12012-05-16 08:02:29 +00001457 if( mpi_cmp_int( E, 0 ) < 0 )
1458 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1459
1460 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001461 * Init temps and window size
1462 */
1463 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001464 mpi_init( &RR ); mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001465 memset( W, 0, sizeof( W ) );
1466
1467 i = mpi_msb( E );
1468
1469 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1470 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1471
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001472 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1473 wsize = POLARSSL_MPI_WINDOW_SIZE;
1474
Paul Bakker5121ce52009-01-03 21:22:43 +00001475 j = N->n + 1;
1476 MPI_CHK( mpi_grow( X, j ) );
1477 MPI_CHK( mpi_grow( &W[1], j ) );
1478 MPI_CHK( mpi_grow( &T, j * 2 ) );
1479
1480 /*
Paul Bakker50546922012-05-19 08:40:49 +00001481 * Compensate for negative A (and correct at the end)
1482 */
1483 neg = ( A->s == -1 );
1484
1485 mpi_init( &Apos );
1486 if( neg )
1487 {
1488 MPI_CHK( mpi_copy( &Apos, A ) );
1489 Apos.s = 1;
1490 A = &Apos;
1491 }
1492
1493 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001494 * If 1st call, pre-compute R^2 mod N
1495 */
1496 if( _RR == NULL || _RR->p == NULL )
1497 {
1498 MPI_CHK( mpi_lset( &RR, 1 ) );
1499 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1500 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1501
1502 if( _RR != NULL )
1503 memcpy( _RR, &RR, sizeof( mpi ) );
1504 }
1505 else
1506 memcpy( &RR, _RR, sizeof( mpi ) );
1507
1508 /*
1509 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1510 */
1511 if( mpi_cmp_mpi( A, N ) >= 0 )
1512 mpi_mod_mpi( &W[1], A, N );
1513 else mpi_copy( &W[1], A );
1514
1515 mpi_montmul( &W[1], &RR, N, mm, &T );
1516
1517 /*
1518 * X = R^2 * R^-1 mod N = R mod N
1519 */
1520 MPI_CHK( mpi_copy( X, &RR ) );
1521 mpi_montred( X, N, mm, &T );
1522
1523 if( wsize > 1 )
1524 {
1525 /*
1526 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1527 */
Paul Bakker23986e52011-04-24 08:57:21 +00001528 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001529
1530 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1531 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1532
1533 for( i = 0; i < wsize - 1; i++ )
1534 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001535
Paul Bakker5121ce52009-01-03 21:22:43 +00001536 /*
1537 * W[i] = W[i - 1] * W[1]
1538 */
Paul Bakker23986e52011-04-24 08:57:21 +00001539 for( i = j + 1; i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001540 {
1541 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1542 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1543
1544 mpi_montmul( &W[i], &W[1], N, mm, &T );
1545 }
1546 }
1547
1548 nblimbs = E->n;
1549 bufsize = 0;
1550 nbits = 0;
1551 wbits = 0;
1552 state = 0;
1553
1554 while( 1 )
1555 {
1556 if( bufsize == 0 )
1557 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001558 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001559 break;
1560
Paul Bakker0d7702c2013-10-29 16:18:35 +01001561 nblimbs--;
1562
Paul Bakkera755ca12011-04-24 09:11:17 +00001563 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001564 }
1565
1566 bufsize--;
1567
1568 ei = (E->p[nblimbs] >> bufsize) & 1;
1569
1570 /*
1571 * skip leading 0s
1572 */
1573 if( ei == 0 && state == 0 )
1574 continue;
1575
1576 if( ei == 0 && state == 1 )
1577 {
1578 /*
1579 * out of window, square X
1580 */
1581 mpi_montmul( X, X, N, mm, &T );
1582 continue;
1583 }
1584
1585 /*
1586 * add ei to current window
1587 */
1588 state = 2;
1589
1590 nbits++;
1591 wbits |= (ei << (wsize - nbits));
1592
1593 if( nbits == wsize )
1594 {
1595 /*
1596 * X = X^wsize R^-1 mod N
1597 */
1598 for( i = 0; i < wsize; i++ )
1599 mpi_montmul( X, X, N, mm, &T );
1600
1601 /*
1602 * X = X * W[wbits] R^-1 mod N
1603 */
1604 mpi_montmul( X, &W[wbits], N, mm, &T );
1605
1606 state--;
1607 nbits = 0;
1608 wbits = 0;
1609 }
1610 }
1611
1612 /*
1613 * process the remaining bits
1614 */
1615 for( i = 0; i < nbits; i++ )
1616 {
1617 mpi_montmul( X, X, N, mm, &T );
1618
1619 wbits <<= 1;
1620
Paul Bakker23986e52011-04-24 08:57:21 +00001621 if( (wbits & (one << wsize)) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001622 mpi_montmul( X, &W[1], N, mm, &T );
1623 }
1624
1625 /*
1626 * X = A^E * R * R^-1 mod N = A^E mod N
1627 */
1628 mpi_montred( X, N, mm, &T );
1629
Paul Bakkerf6198c12012-05-16 08:02:29 +00001630 if( neg )
1631 {
1632 X->s = -1;
1633 mpi_add_mpi( X, N, X );
1634 }
1635
Paul Bakker5121ce52009-01-03 21:22:43 +00001636cleanup:
1637
Paul Bakker23986e52011-04-24 08:57:21 +00001638 for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001639 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001640
Paul Bakkerf6198c12012-05-16 08:02:29 +00001641 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001642
1643 if( _RR == NULL )
1644 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001645
1646 return( ret );
1647}
1648
Paul Bakker5121ce52009-01-03 21:22:43 +00001649/*
1650 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1651 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001652int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001653{
Paul Bakker23986e52011-04-24 08:57:21 +00001654 int ret;
1655 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001656 mpi TG, TA, TB;
1657
Paul Bakker6c591fa2011-05-05 11:49:20 +00001658 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001659
Paul Bakker5121ce52009-01-03 21:22:43 +00001660 MPI_CHK( mpi_copy( &TA, A ) );
1661 MPI_CHK( mpi_copy( &TB, B ) );
1662
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001663 lz = mpi_lsb( &TA );
1664 lzt = mpi_lsb( &TB );
1665
1666 if ( lzt < lz )
1667 lz = lzt;
1668
1669 MPI_CHK( mpi_shift_r( &TA, lz ) );
1670 MPI_CHK( mpi_shift_r( &TB, lz ) );
1671
Paul Bakker5121ce52009-01-03 21:22:43 +00001672 TA.s = TB.s = 1;
1673
1674 while( mpi_cmp_int( &TA, 0 ) != 0 )
1675 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001676 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1677 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001678
1679 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1680 {
1681 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1682 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1683 }
1684 else
1685 {
1686 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1687 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1688 }
1689 }
1690
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001691 MPI_CHK( mpi_shift_l( &TB, lz ) );
1692 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001693
1694cleanup:
1695
Paul Bakker6c591fa2011-05-05 11:49:20 +00001696 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001697
1698 return( ret );
1699}
1700
Paul Bakkera3d195c2011-11-27 21:07:34 +00001701int mpi_fill_random( mpi *X, size_t size,
1702 int (*f_rng)(void *, unsigned char *, size_t),
1703 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001704{
Paul Bakker23986e52011-04-24 08:57:21 +00001705 int ret;
Paul Bakker287781a2011-03-26 13:18:49 +00001706
Paul Bakker39dfdac2012-02-12 17:17:27 +00001707 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001708 MPI_CHK( mpi_lset( X, 0 ) );
1709
Paul Bakker39dfdac2012-02-12 17:17:27 +00001710 MPI_CHK( f_rng( p_rng, (unsigned char *) X->p, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001711
1712cleanup:
1713 return( ret );
1714}
1715
Paul Bakker5121ce52009-01-03 21:22:43 +00001716/*
1717 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1718 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001719int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001720{
1721 int ret;
1722 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1723
1724 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001725 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001726
Paul Bakker6c591fa2011-05-05 11:49:20 +00001727 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1728 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1729 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001730
1731 MPI_CHK( mpi_gcd( &G, A, N ) );
1732
1733 if( mpi_cmp_int( &G, 1 ) != 0 )
1734 {
Paul Bakker40e46942009-01-03 21:51:57 +00001735 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001736 goto cleanup;
1737 }
1738
1739 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1740 MPI_CHK( mpi_copy( &TU, &TA ) );
1741 MPI_CHK( mpi_copy( &TB, N ) );
1742 MPI_CHK( mpi_copy( &TV, N ) );
1743
1744 MPI_CHK( mpi_lset( &U1, 1 ) );
1745 MPI_CHK( mpi_lset( &U2, 0 ) );
1746 MPI_CHK( mpi_lset( &V1, 0 ) );
1747 MPI_CHK( mpi_lset( &V2, 1 ) );
1748
1749 do
1750 {
1751 while( ( TU.p[0] & 1 ) == 0 )
1752 {
1753 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1754
1755 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1756 {
1757 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1758 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1759 }
1760
1761 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1762 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1763 }
1764
1765 while( ( TV.p[0] & 1 ) == 0 )
1766 {
1767 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1768
1769 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1770 {
1771 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1772 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1773 }
1774
1775 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1776 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1777 }
1778
1779 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1780 {
1781 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1782 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1783 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1784 }
1785 else
1786 {
1787 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1788 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1789 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1790 }
1791 }
1792 while( mpi_cmp_int( &TU, 0 ) != 0 );
1793
1794 while( mpi_cmp_int( &V1, 0 ) < 0 )
1795 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1796
1797 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1798 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1799
1800 MPI_CHK( mpi_copy( X, &V1 ) );
1801
1802cleanup:
1803
Paul Bakker6c591fa2011-05-05 11:49:20 +00001804 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1805 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1806 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001807
1808 return( ret );
1809}
1810
Paul Bakkerd9374b02012-11-02 11:02:58 +00001811#if defined(POLARSSL_GENPRIME)
1812
Paul Bakker5121ce52009-01-03 21:22:43 +00001813static const int small_prime[] =
1814{
1815 3, 5, 7, 11, 13, 17, 19, 23,
1816 29, 31, 37, 41, 43, 47, 53, 59,
1817 61, 67, 71, 73, 79, 83, 89, 97,
1818 101, 103, 107, 109, 113, 127, 131, 137,
1819 139, 149, 151, 157, 163, 167, 173, 179,
1820 181, 191, 193, 197, 199, 211, 223, 227,
1821 229, 233, 239, 241, 251, 257, 263, 269,
1822 271, 277, 281, 283, 293, 307, 311, 313,
1823 317, 331, 337, 347, 349, 353, 359, 367,
1824 373, 379, 383, 389, 397, 401, 409, 419,
1825 421, 431, 433, 439, 443, 449, 457, 461,
1826 463, 467, 479, 487, 491, 499, 503, 509,
1827 521, 523, 541, 547, 557, 563, 569, 571,
1828 577, 587, 593, 599, 601, 607, 613, 617,
1829 619, 631, 641, 643, 647, 653, 659, 661,
1830 673, 677, 683, 691, 701, 709, 719, 727,
1831 733, 739, 743, 751, 757, 761, 769, 773,
1832 787, 797, 809, 811, 821, 823, 827, 829,
1833 839, 853, 857, 859, 863, 877, 881, 883,
1834 887, 907, 911, 919, 929, 937, 941, 947,
1835 953, 967, 971, 977, 983, 991, 997, -103
1836};
1837
1838/*
1839 * Miller-Rabin primality test (HAC 4.24)
1840 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001841int mpi_is_prime( mpi *X,
1842 int (*f_rng)(void *, unsigned char *, size_t),
1843 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001844{
Paul Bakker23986e52011-04-24 08:57:21 +00001845 int ret, xs;
1846 size_t i, j, n, s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001847 mpi W, R, T, A, RR;
Paul Bakker5121ce52009-01-03 21:22:43 +00001848
Paul Bakker48eab262009-06-25 21:25:49 +00001849 if( mpi_cmp_int( X, 0 ) == 0 ||
1850 mpi_cmp_int( X, 1 ) == 0 )
1851 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1852
1853 if( mpi_cmp_int( X, 2 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001854 return( 0 );
1855
Paul Bakker6c591fa2011-05-05 11:49:20 +00001856 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
1857 mpi_init( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001858
1859 xs = X->s; X->s = 1;
1860
1861 /*
1862 * test trivial factors first
1863 */
1864 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001865 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001866
1867 for( i = 0; small_prime[i] > 0; i++ )
1868 {
Paul Bakkera755ca12011-04-24 09:11:17 +00001869 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001870
1871 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
1872 return( 0 );
1873
1874 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1875
1876 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001877 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001878 }
1879
1880 /*
1881 * W = |X| - 1
1882 * R = W >> lsb( W )
1883 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001884 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001885 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001886 MPI_CHK( mpi_copy( &R, &W ) );
1887 MPI_CHK( mpi_shift_r( &R, s ) );
1888
1889 i = mpi_msb( X );
1890 /*
1891 * HAC, table 4.4
1892 */
1893 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1894 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1895 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1896
1897 for( i = 0; i < n; i++ )
1898 {
1899 /*
1900 * pick a random A, 1 < A < |X| - 1
1901 */
Paul Bakker901c6562012-04-20 13:25:38 +00001902 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001903
Paul Bakkerb94081b2011-01-05 15:53:06 +00001904 if( mpi_cmp_mpi( &A, &W ) >= 0 )
1905 {
1906 j = mpi_msb( &A ) - mpi_msb( &W );
1907 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1908 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001909 A.p[0] |= 3;
1910
1911 /*
1912 * A = A^R mod |X|
1913 */
1914 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1915
1916 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1917 mpi_cmp_int( &A, 1 ) == 0 )
1918 continue;
1919
1920 j = 1;
1921 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1922 {
1923 /*
1924 * A = A * A mod |X|
1925 */
1926 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1927 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1928
1929 if( mpi_cmp_int( &A, 1 ) == 0 )
1930 break;
1931
1932 j++;
1933 }
1934
1935 /*
1936 * not prime if A != |X| - 1 or A == 1
1937 */
1938 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1939 mpi_cmp_int( &A, 1 ) == 0 )
1940 {
Paul Bakker40e46942009-01-03 21:51:57 +00001941 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001942 break;
1943 }
1944 }
1945
1946cleanup:
1947
1948 X->s = xs;
1949
Paul Bakker6c591fa2011-05-05 11:49:20 +00001950 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
1951 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001952
1953 return( ret );
1954}
1955
1956/*
1957 * Prime number generation
1958 */
Paul Bakker23986e52011-04-24 08:57:21 +00001959int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001960 int (*f_rng)(void *, unsigned char *, size_t),
1961 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001962{
Paul Bakker23986e52011-04-24 08:57:21 +00001963 int ret;
1964 size_t k, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001965 mpi Y;
1966
Paul Bakkerfe3256e2011-11-25 12:11:43 +00001967 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00001968 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
Paul Bakker6c591fa2011-05-05 11:49:20 +00001970 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001971
1972 n = BITS_TO_LIMBS( nbits );
1973
Paul Bakker901c6562012-04-20 13:25:38 +00001974 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001975
1976 k = mpi_msb( X );
1977 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
1978 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
1979
1980 X->p[0] |= 3;
1981
1982 if( dh_flag == 0 )
1983 {
1984 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
1985 {
Paul Bakker40e46942009-01-03 21:51:57 +00001986 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001987 goto cleanup;
1988
1989 MPI_CHK( mpi_add_int( X, X, 2 ) );
1990 }
1991 }
1992 else
1993 {
1994 MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
1995 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1996
1997 while( 1 )
1998 {
1999 if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
2000 {
2001 if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
2002 break;
2003
Paul Bakker40e46942009-01-03 21:51:57 +00002004 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002005 goto cleanup;
2006 }
2007
Paul Bakker40e46942009-01-03 21:51:57 +00002008 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002009 goto cleanup;
2010
2011 MPI_CHK( mpi_add_int( &Y, X, 1 ) );
2012 MPI_CHK( mpi_add_int( X, X, 2 ) );
2013 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2014 }
2015 }
2016
2017cleanup:
2018
Paul Bakker6c591fa2011-05-05 11:49:20 +00002019 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002020
2021 return( ret );
2022}
2023
Manuel Pégourié-Gonnarddf0142b2013-08-22 18:29:07 +02002024#endif /* POLARSSL_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002025
Paul Bakker40e46942009-01-03 21:51:57 +00002026#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002027
Paul Bakker23986e52011-04-24 08:57:21 +00002028#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002029
2030static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2031{
2032 { 693, 609, 21 },
2033 { 1764, 868, 28 },
2034 { 768454923, 542167814, 1 }
2035};
2036
Paul Bakker5121ce52009-01-03 21:22:43 +00002037/*
2038 * Checkup routine
2039 */
2040int mpi_self_test( int verbose )
2041{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002042 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002043 mpi A, E, N, X, Y, U, V;
2044
Paul Bakker6c591fa2011-05-05 11:49:20 +00002045 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2046 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002047
2048 MPI_CHK( mpi_read_string( &A, 16,
2049 "EFE021C2645FD1DC586E69184AF4A31E" \
2050 "D5F53E93B5F123FA41680867BA110131" \
2051 "944FE7952E2517337780CB0DB80E61AA" \
2052 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2053
2054 MPI_CHK( mpi_read_string( &E, 16,
2055 "B2E7EFD37075B9F03FF989C7C5051C20" \
2056 "34D2A323810251127E7BF8625A4F49A5" \
2057 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2058 "5B5C25763222FEFCCFC38B832366C29E" ) );
2059
2060 MPI_CHK( mpi_read_string( &N, 16,
2061 "0066A198186C18C10B2F5ED9B522752A" \
2062 "9830B69916E535C8F047518A889A43A5" \
2063 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2064
2065 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2066
2067 MPI_CHK( mpi_read_string( &U, 16,
2068 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2069 "9E857EA95A03512E2BAE7391688D264A" \
2070 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2071 "8001B72E848A38CAE1C65F78E56ABDEF" \
2072 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2073 "ECF677152EF804370C1A305CAF3B5BF1" \
2074 "30879B56C61DE584A0F53A2447A51E" ) );
2075
2076 if( verbose != 0 )
2077 printf( " MPI test #1 (mul_mpi): " );
2078
2079 if( mpi_cmp_mpi( &X, &U ) != 0 )
2080 {
2081 if( verbose != 0 )
2082 printf( "failed\n" );
2083
2084 return( 1 );
2085 }
2086
2087 if( verbose != 0 )
2088 printf( "passed\n" );
2089
2090 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2091
2092 MPI_CHK( mpi_read_string( &U, 16,
2093 "256567336059E52CAE22925474705F39A94" ) );
2094
2095 MPI_CHK( mpi_read_string( &V, 16,
2096 "6613F26162223DF488E9CD48CC132C7A" \
2097 "0AC93C701B001B092E4E5B9F73BCD27B" \
2098 "9EE50D0657C77F374E903CDFA4C642" ) );
2099
2100 if( verbose != 0 )
2101 printf( " MPI test #2 (div_mpi): " );
2102
2103 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2104 mpi_cmp_mpi( &Y, &V ) != 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_exp_mod( &X, &A, &E, &N, NULL ) );
2116
2117 MPI_CHK( mpi_read_string( &U, 16,
2118 "36E139AEA55215609D2816998ED020BB" \
2119 "BD96C37890F65171D948E9BC7CBAA4D9" \
2120 "325D24D6A3C12710F10A09FA08AB87" ) );
2121
2122 if( verbose != 0 )
2123 printf( " MPI test #3 (exp_mod): " );
2124
2125 if( mpi_cmp_mpi( &X, &U ) != 0 )
2126 {
2127 if( verbose != 0 )
2128 printf( "failed\n" );
2129
2130 return( 1 );
2131 }
2132
2133 if( verbose != 0 )
2134 printf( "passed\n" );
2135
2136 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2137
2138 MPI_CHK( mpi_read_string( &U, 16,
2139 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2140 "C3DBA76456363A10869622EAC2DD84EC" \
2141 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2142
2143 if( verbose != 0 )
2144 printf( " MPI test #4 (inv_mod): " );
2145
2146 if( mpi_cmp_mpi( &X, &U ) != 0 )
2147 {
2148 if( verbose != 0 )
2149 printf( "failed\n" );
2150
2151 return( 1 );
2152 }
2153
2154 if( verbose != 0 )
2155 printf( "passed\n" );
2156
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002157 if( verbose != 0 )
2158 printf( " MPI test #5 (simple gcd): " );
2159
2160 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2161 {
2162 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002163 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002164
Paul Bakker23986e52011-04-24 08:57:21 +00002165 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002166
Paul Bakker23986e52011-04-24 08:57:21 +00002167 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2168 {
2169 if( verbose != 0 )
2170 printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002171
Paul Bakker23986e52011-04-24 08:57:21 +00002172 return( 1 );
2173 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002174 }
2175
2176 if( verbose != 0 )
2177 printf( "passed\n" );
2178
Paul Bakker5121ce52009-01-03 21:22:43 +00002179cleanup:
2180
2181 if( ret != 0 && verbose != 0 )
2182 printf( "Unexpected error, return code = %08X\n", ret );
2183
Paul Bakker6c591fa2011-05-05 11:49:20 +00002184 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2185 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002186
2187 if( verbose != 0 )
2188 printf( "\n" );
2189
2190 return( ret );
2191}
2192
2193#endif
2194
2195#endif