blob: 49321bb654c7c1a70bc7f35d358af818168d6a8a [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 */
Manuel Pégourié-Gonnard3e3d2b82013-11-21 21:12:26 +0100225 X->s = X->s * (1 - assign) + Y->s * assign;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100226 for( i = 0; i < X->n; i++ )
227 X->p[i] = X->p[i] * (1 - assign) + Y->p[i] * assign;
228
229cleanup:
230 return( ret );
231}
232
233/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000234 * Set value from integer
235 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000236int mpi_lset( mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000237{
238 int ret;
239
240 MPI_CHK( mpi_grow( X, 1 ) );
241 memset( X->p, 0, X->n * ciL );
242
243 X->p[0] = ( z < 0 ) ? -z : z;
244 X->s = ( z < 0 ) ? -1 : 1;
245
246cleanup:
247
248 return( ret );
249}
250
251/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000252 * Get a specific bit
253 */
Paul Bakker6b906e52012-05-08 12:01:43 +0000254int mpi_get_bit( const mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000255{
256 if( X->n * biL <= pos )
257 return( 0 );
258
259 return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
260}
261
262/*
263 * Set a bit to a specific value of 0 or 1
264 */
265int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
266{
267 int ret = 0;
268 size_t off = pos / biL;
269 size_t idx = pos % biL;
270
271 if( val != 0 && val != 1 )
272 return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
273
274 if( X->n * biL <= pos )
275 {
276 if( val == 0 )
277 return ( 0 );
278
279 MPI_CHK( mpi_grow( X, off + 1 ) );
280 }
281
282 X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
283
284cleanup:
285
286 return( ret );
287}
288
289/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000290 * Return the number of least significant bits
291 */
Paul Bakker23986e52011-04-24 08:57:21 +0000292size_t mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000293{
Paul Bakker23986e52011-04-24 08:57:21 +0000294 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000295
296 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000297 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000298 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
299 return( count );
300
301 return( 0 );
302}
303
304/*
305 * Return the number of most significant bits
306 */
Paul Bakker23986e52011-04-24 08:57:21 +0000307size_t mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000308{
Paul Bakker23986e52011-04-24 08:57:21 +0000309 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000310
311 for( i = X->n - 1; i > 0; i-- )
312 if( X->p[i] != 0 )
313 break;
314
Paul Bakker23986e52011-04-24 08:57:21 +0000315 for( j = biL; j > 0; j-- )
316 if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000317 break;
318
Paul Bakker23986e52011-04-24 08:57:21 +0000319 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000320}
321
322/*
323 * Return the total size in bytes
324 */
Paul Bakker23986e52011-04-24 08:57:21 +0000325size_t mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000326{
327 return( ( mpi_msb( X ) + 7 ) >> 3 );
328}
329
330/*
331 * Convert an ASCII character to digit value
332 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000333static int mpi_get_digit( t_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000334{
335 *d = 255;
336
337 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
338 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
339 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
340
Paul Bakkera755ca12011-04-24 09:11:17 +0000341 if( *d >= (t_uint) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000342 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000343
344 return( 0 );
345}
346
347/*
348 * Import from an ASCII string
349 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000350int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000351{
Paul Bakker23986e52011-04-24 08:57:21 +0000352 int ret;
353 size_t i, j, slen, n;
Paul Bakkera755ca12011-04-24 09:11:17 +0000354 t_uint d;
Paul Bakker5121ce52009-01-03 21:22:43 +0000355 mpi T;
356
357 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000358 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000359
Paul Bakker6c591fa2011-05-05 11:49:20 +0000360 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000361
Paul Bakkerff60ee62010-03-16 21:09:09 +0000362 slen = strlen( s );
363
Paul Bakker5121ce52009-01-03 21:22:43 +0000364 if( radix == 16 )
365 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000366 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000367
368 MPI_CHK( mpi_grow( X, n ) );
369 MPI_CHK( mpi_lset( X, 0 ) );
370
Paul Bakker23986e52011-04-24 08:57:21 +0000371 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000372 {
Paul Bakker23986e52011-04-24 08:57:21 +0000373 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000374 {
375 X->s = -1;
376 break;
377 }
378
Paul Bakker23986e52011-04-24 08:57:21 +0000379 MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000380 X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
381 }
382 }
383 else
384 {
385 MPI_CHK( mpi_lset( X, 0 ) );
386
Paul Bakkerff60ee62010-03-16 21:09:09 +0000387 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000388 {
389 if( i == 0 && s[i] == '-' )
390 {
391 X->s = -1;
392 continue;
393 }
394
395 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
396 MPI_CHK( mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000397
398 if( X->s == 1 )
399 {
400 MPI_CHK( mpi_add_int( X, &T, d ) );
401 }
402 else
403 {
404 MPI_CHK( mpi_sub_int( X, &T, d ) );
405 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000406 }
407 }
408
409cleanup:
410
Paul Bakker6c591fa2011-05-05 11:49:20 +0000411 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000412
413 return( ret );
414}
415
416/*
417 * Helper to write the digits high-order first
418 */
419static int mpi_write_hlp( mpi *X, int radix, char **p )
420{
421 int ret;
Paul Bakkera755ca12011-04-24 09:11:17 +0000422 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000423
424 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000425 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
427 MPI_CHK( mpi_mod_int( &r, X, radix ) );
428 MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
429
430 if( mpi_cmp_int( X, 0 ) != 0 )
431 MPI_CHK( mpi_write_hlp( X, radix, p ) );
432
433 if( r < 10 )
434 *(*p)++ = (char)( r + 0x30 );
435 else
436 *(*p)++ = (char)( r + 0x37 );
437
438cleanup:
439
440 return( ret );
441}
442
443/*
444 * Export into an ASCII string
445 */
Paul Bakker23986e52011-04-24 08:57:21 +0000446int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000447{
Paul Bakker23986e52011-04-24 08:57:21 +0000448 int ret = 0;
449 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000450 char *p;
451 mpi T;
452
453 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000454 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000455
456 n = mpi_msb( X );
457 if( radix >= 4 ) n >>= 1;
458 if( radix >= 16 ) n >>= 1;
459 n += 3;
460
461 if( *slen < n )
462 {
463 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000464 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000465 }
466
467 p = s;
Paul Bakker6c591fa2011-05-05 11:49:20 +0000468 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
470 if( X->s == -1 )
471 *p++ = '-';
472
473 if( radix == 16 )
474 {
Paul Bakker23986e52011-04-24 08:57:21 +0000475 int c;
476 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000477
Paul Bakker23986e52011-04-24 08:57:21 +0000478 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000479 {
Paul Bakker23986e52011-04-24 08:57:21 +0000480 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000481 {
Paul Bakker23986e52011-04-24 08:57:21 +0000482 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
Paul Bakker23986e52011-04-24 08:57:21 +0000484 if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000485 continue;
486
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000487 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000488 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000489 k = 1;
490 }
491 }
492 }
493 else
494 {
495 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000496
497 if( T.s == -1 )
498 T.s = 1;
499
Paul Bakker5121ce52009-01-03 21:22:43 +0000500 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
501 }
502
503 *p++ = '\0';
504 *slen = p - s;
505
506cleanup:
507
Paul Bakker6c591fa2011-05-05 11:49:20 +0000508 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000509
510 return( ret );
511}
512
Paul Bakker335db3f2011-04-25 15:28:35 +0000513#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000514/*
515 * Read X from an opened file
516 */
517int mpi_read_file( mpi *X, int radix, FILE *fin )
518{
Paul Bakkera755ca12011-04-24 09:11:17 +0000519 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000520 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000521 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000522 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000523 * Buffer should have space for (short) label and decimal formatted MPI,
524 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000525 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000526 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000527
528 memset( s, 0, sizeof( s ) );
529 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000530 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000531
532 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000533 if( slen == sizeof( s ) - 2 )
534 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
535
Paul Bakker5121ce52009-01-03 21:22:43 +0000536 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
537 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
538
539 p = s + slen;
540 while( --p >= s )
541 if( mpi_get_digit( &d, radix, *p ) != 0 )
542 break;
543
544 return( mpi_read_string( X, radix, p + 1 ) );
545}
546
547/*
548 * Write X into an opened file (or stdout if fout == NULL)
549 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000550int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000551{
Paul Bakker23986e52011-04-24 08:57:21 +0000552 int ret;
553 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000554 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000555 * Buffer should have space for (short) label and decimal formatted MPI,
556 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000557 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000558 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000559
560 n = sizeof( s );
561 memset( s, 0, n );
562 n -= 2;
563
Paul Bakker23986e52011-04-24 08:57:21 +0000564 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000565
566 if( p == NULL ) p = "";
567
568 plen = strlen( p );
569 slen = strlen( s );
570 s[slen++] = '\r';
571 s[slen++] = '\n';
572
573 if( fout != NULL )
574 {
575 if( fwrite( p, 1, plen, fout ) != plen ||
576 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000577 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000578 }
579 else
580 printf( "%s%s", p, s );
581
582cleanup:
583
584 return( ret );
585}
Paul Bakker335db3f2011-04-25 15:28:35 +0000586#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000587
588/*
589 * Import X from unsigned binary data, big endian
590 */
Paul Bakker23986e52011-04-24 08:57:21 +0000591int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000592{
Paul Bakker23986e52011-04-24 08:57:21 +0000593 int ret;
594 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000595
596 for( n = 0; n < buflen; n++ )
597 if( buf[n] != 0 )
598 break;
599
600 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
601 MPI_CHK( mpi_lset( X, 0 ) );
602
Paul Bakker23986e52011-04-24 08:57:21 +0000603 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000604 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000605
606cleanup:
607
608 return( ret );
609}
610
611/*
612 * Export X into unsigned binary data, big endian
613 */
Paul Bakker23986e52011-04-24 08:57:21 +0000614int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000615{
Paul Bakker23986e52011-04-24 08:57:21 +0000616 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000617
618 n = mpi_size( X );
619
620 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000621 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000622
623 memset( buf, 0, buflen );
624
625 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
626 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
627
628 return( 0 );
629}
630
631/*
632 * Left-shift: X <<= count
633 */
Paul Bakker23986e52011-04-24 08:57:21 +0000634int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000635{
Paul Bakker23986e52011-04-24 08:57:21 +0000636 int ret;
637 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000638 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000639
640 v0 = count / (biL );
641 t1 = count & (biL - 1);
642
643 i = mpi_msb( X ) + count;
644
Paul Bakkerf9688572011-05-05 10:00:45 +0000645 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000646 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
647
648 ret = 0;
649
650 /*
651 * shift by count / limb_size
652 */
653 if( v0 > 0 )
654 {
Paul Bakker23986e52011-04-24 08:57:21 +0000655 for( i = X->n; i > v0; i-- )
656 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000657
Paul Bakker23986e52011-04-24 08:57:21 +0000658 for( ; i > 0; i-- )
659 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000660 }
661
662 /*
663 * shift by count % limb_size
664 */
665 if( t1 > 0 )
666 {
667 for( i = v0; i < X->n; i++ )
668 {
669 r1 = X->p[i] >> (biL - t1);
670 X->p[i] <<= t1;
671 X->p[i] |= r0;
672 r0 = r1;
673 }
674 }
675
676cleanup:
677
678 return( ret );
679}
680
681/*
682 * Right-shift: X >>= count
683 */
Paul Bakker23986e52011-04-24 08:57:21 +0000684int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000685{
Paul Bakker23986e52011-04-24 08:57:21 +0000686 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000687 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000688
689 v0 = count / biL;
690 v1 = count & (biL - 1);
691
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100692 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
693 return mpi_lset( X, 0 );
694
Paul Bakker5121ce52009-01-03 21:22:43 +0000695 /*
696 * shift by count / limb_size
697 */
698 if( v0 > 0 )
699 {
700 for( i = 0; i < X->n - v0; i++ )
701 X->p[i] = X->p[i + v0];
702
703 for( ; i < X->n; i++ )
704 X->p[i] = 0;
705 }
706
707 /*
708 * shift by count % limb_size
709 */
710 if( v1 > 0 )
711 {
Paul Bakker23986e52011-04-24 08:57:21 +0000712 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000713 {
Paul Bakker23986e52011-04-24 08:57:21 +0000714 r1 = X->p[i - 1] << (biL - v1);
715 X->p[i - 1] >>= v1;
716 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000717 r0 = r1;
718 }
719 }
720
721 return( 0 );
722}
723
724/*
725 * Compare unsigned values
726 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000727int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000728{
Paul Bakker23986e52011-04-24 08:57:21 +0000729 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000730
Paul Bakker23986e52011-04-24 08:57:21 +0000731 for( i = X->n; i > 0; i-- )
732 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000733 break;
734
Paul Bakker23986e52011-04-24 08:57:21 +0000735 for( j = Y->n; j > 0; j-- )
736 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000737 break;
738
Paul Bakker23986e52011-04-24 08:57:21 +0000739 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000740 return( 0 );
741
742 if( i > j ) return( 1 );
743 if( j > i ) return( -1 );
744
Paul Bakker23986e52011-04-24 08:57:21 +0000745 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000746 {
Paul Bakker23986e52011-04-24 08:57:21 +0000747 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
748 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000749 }
750
751 return( 0 );
752}
753
754/*
755 * Compare signed values
756 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000757int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000758{
Paul Bakker23986e52011-04-24 08:57:21 +0000759 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000760
Paul Bakker23986e52011-04-24 08:57:21 +0000761 for( i = X->n; i > 0; i-- )
762 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000763 break;
764
Paul Bakker23986e52011-04-24 08:57:21 +0000765 for( j = Y->n; j > 0; j-- )
766 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000767 break;
768
Paul Bakker23986e52011-04-24 08:57:21 +0000769 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000770 return( 0 );
771
772 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000773 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000774
775 if( X->s > 0 && Y->s < 0 ) return( 1 );
776 if( Y->s > 0 && X->s < 0 ) return( -1 );
777
Paul Bakker23986e52011-04-24 08:57:21 +0000778 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000779 {
Paul Bakker23986e52011-04-24 08:57:21 +0000780 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
781 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000782 }
783
784 return( 0 );
785}
786
787/*
788 * Compare signed values
789 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000790int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000791{
792 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000793 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000794
795 *p = ( z < 0 ) ? -z : z;
796 Y.s = ( z < 0 ) ? -1 : 1;
797 Y.n = 1;
798 Y.p = p;
799
800 return( mpi_cmp_mpi( X, &Y ) );
801}
802
803/*
804 * Unsigned addition: X = |A| + |B| (HAC 14.7)
805 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000806int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000807{
Paul Bakker23986e52011-04-24 08:57:21 +0000808 int ret;
809 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000810 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000811
812 if( X == B )
813 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000814 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000815 }
816
817 if( X != A )
818 MPI_CHK( mpi_copy( X, A ) );
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000819
820 /*
821 * X should always be positive as a result of unsigned additions.
822 */
823 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000824
Paul Bakker23986e52011-04-24 08:57:21 +0000825 for( j = B->n; j > 0; j-- )
826 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000827 break;
828
Paul Bakker23986e52011-04-24 08:57:21 +0000829 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000830
831 o = B->p; p = X->p; c = 0;
832
Paul Bakker23986e52011-04-24 08:57:21 +0000833 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000834 {
835 *p += c; c = ( *p < c );
836 *p += *o; c += ( *p < *o );
837 }
838
839 while( c != 0 )
840 {
841 if( i >= X->n )
842 {
843 MPI_CHK( mpi_grow( X, i + 1 ) );
844 p = X->p + i;
845 }
846
Paul Bakker2d319fd2012-09-16 21:34:26 +0000847 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000848 }
849
850cleanup:
851
852 return( ret );
853}
854
855/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100856 * Helper for mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000857 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000858static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000859{
Paul Bakker23986e52011-04-24 08:57:21 +0000860 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000861 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000862
863 for( i = c = 0; i < n; i++, s++, d++ )
864 {
865 z = ( *d < c ); *d -= c;
866 c = ( *d < *s ) + z; *d -= *s;
867 }
868
869 while( c != 0 )
870 {
871 z = ( *d < c ); *d -= c;
872 c = z; i++; d++;
873 }
874}
875
876/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100877 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000878 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000879int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000880{
881 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000882 int ret;
883 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000884
885 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000886 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000887
Paul Bakker6c591fa2011-05-05 11:49:20 +0000888 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000889
890 if( X == B )
891 {
892 MPI_CHK( mpi_copy( &TB, B ) );
893 B = &TB;
894 }
895
896 if( X != A )
897 MPI_CHK( mpi_copy( X, A ) );
898
Paul Bakker1ef7a532009-06-20 10:50:55 +0000899 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100900 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000901 */
902 X->s = 1;
903
Paul Bakker5121ce52009-01-03 21:22:43 +0000904 ret = 0;
905
Paul Bakker23986e52011-04-24 08:57:21 +0000906 for( n = B->n; n > 0; n-- )
907 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000908 break;
909
Paul Bakker23986e52011-04-24 08:57:21 +0000910 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000911
912cleanup:
913
Paul Bakker6c591fa2011-05-05 11:49:20 +0000914 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000915
916 return( ret );
917}
918
919/*
920 * Signed addition: X = A + B
921 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000922int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000923{
924 int ret, s = A->s;
925
926 if( A->s * B->s < 0 )
927 {
928 if( mpi_cmp_abs( A, B ) >= 0 )
929 {
930 MPI_CHK( mpi_sub_abs( X, A, B ) );
931 X->s = s;
932 }
933 else
934 {
935 MPI_CHK( mpi_sub_abs( X, B, A ) );
936 X->s = -s;
937 }
938 }
939 else
940 {
941 MPI_CHK( mpi_add_abs( X, A, B ) );
942 X->s = s;
943 }
944
945cleanup:
946
947 return( ret );
948}
949
950/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100951 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +0000952 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000953int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000954{
955 int ret, s = A->s;
956
957 if( A->s * B->s > 0 )
958 {
959 if( mpi_cmp_abs( A, B ) >= 0 )
960 {
961 MPI_CHK( mpi_sub_abs( X, A, B ) );
962 X->s = s;
963 }
964 else
965 {
966 MPI_CHK( mpi_sub_abs( X, B, A ) );
967 X->s = -s;
968 }
969 }
970 else
971 {
972 MPI_CHK( mpi_add_abs( X, A, B ) );
973 X->s = s;
974 }
975
976cleanup:
977
978 return( ret );
979}
980
981/*
982 * Signed addition: X = A + b
983 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000984int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000985{
986 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000987 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000988
989 p[0] = ( b < 0 ) ? -b : b;
990 _B.s = ( b < 0 ) ? -1 : 1;
991 _B.n = 1;
992 _B.p = p;
993
994 return( mpi_add_mpi( X, A, &_B ) );
995}
996
997/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100998 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +0000999 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001000int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001001{
1002 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001003 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001004
1005 p[0] = ( b < 0 ) ? -b : b;
1006 _B.s = ( b < 0 ) ? -1 : 1;
1007 _B.n = 1;
1008 _B.p = p;
1009
1010 return( mpi_sub_mpi( X, A, &_B ) );
1011}
1012
1013/*
1014 * Helper for mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001015 */
1016static
1017#if defined(__APPLE__) && defined(__arm__)
1018/*
1019 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1020 * appears to need this to prevent bad ARM code generation at -O3.
1021 */
1022__attribute__ ((noinline))
1023#endif
1024void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001025{
Paul Bakkera755ca12011-04-24 09:11:17 +00001026 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001027
1028#if defined(MULADDC_HUIT)
1029 for( ; i >= 8; i -= 8 )
1030 {
1031 MULADDC_INIT
1032 MULADDC_HUIT
1033 MULADDC_STOP
1034 }
1035
1036 for( ; i > 0; i-- )
1037 {
1038 MULADDC_INIT
1039 MULADDC_CORE
1040 MULADDC_STOP
1041 }
1042#else
1043 for( ; i >= 16; i -= 16 )
1044 {
1045 MULADDC_INIT
1046 MULADDC_CORE MULADDC_CORE
1047 MULADDC_CORE MULADDC_CORE
1048 MULADDC_CORE MULADDC_CORE
1049 MULADDC_CORE MULADDC_CORE
1050
1051 MULADDC_CORE MULADDC_CORE
1052 MULADDC_CORE MULADDC_CORE
1053 MULADDC_CORE MULADDC_CORE
1054 MULADDC_CORE MULADDC_CORE
1055 MULADDC_STOP
1056 }
1057
1058 for( ; i >= 8; i -= 8 )
1059 {
1060 MULADDC_INIT
1061 MULADDC_CORE MULADDC_CORE
1062 MULADDC_CORE MULADDC_CORE
1063
1064 MULADDC_CORE MULADDC_CORE
1065 MULADDC_CORE MULADDC_CORE
1066 MULADDC_STOP
1067 }
1068
1069 for( ; i > 0; i-- )
1070 {
1071 MULADDC_INIT
1072 MULADDC_CORE
1073 MULADDC_STOP
1074 }
1075#endif
1076
1077 t++;
1078
1079 do {
1080 *d += c; c = ( *d < c ); d++;
1081 }
1082 while( c != 0 );
1083}
1084
1085/*
1086 * Baseline multiplication: X = A * B (HAC 14.12)
1087 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001088int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001089{
Paul Bakker23986e52011-04-24 08:57:21 +00001090 int ret;
1091 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001092 mpi TA, TB;
1093
Paul Bakker6c591fa2011-05-05 11:49:20 +00001094 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001095
1096 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1097 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1098
Paul Bakker23986e52011-04-24 08:57:21 +00001099 for( i = A->n; i > 0; i-- )
1100 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001101 break;
1102
Paul Bakker23986e52011-04-24 08:57:21 +00001103 for( j = B->n; j > 0; j-- )
1104 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001105 break;
1106
Paul Bakker23986e52011-04-24 08:57:21 +00001107 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001108 MPI_CHK( mpi_lset( X, 0 ) );
1109
Paul Bakker23986e52011-04-24 08:57:21 +00001110 for( i++; j > 0; j-- )
1111 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001112
1113 X->s = A->s * B->s;
1114
1115cleanup:
1116
Paul Bakker6c591fa2011-05-05 11:49:20 +00001117 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001118
1119 return( ret );
1120}
1121
1122/*
1123 * Baseline multiplication: X = A * b
1124 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001125int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001126{
1127 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001128 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001129
1130 _B.s = 1;
1131 _B.n = 1;
1132 _B.p = p;
1133 p[0] = b;
1134
1135 return( mpi_mul_mpi( X, A, &_B ) );
1136}
1137
1138/*
1139 * Division by mpi: A = Q * B + R (HAC 14.20)
1140 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001141int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001142{
Paul Bakker23986e52011-04-24 08:57:21 +00001143 int ret;
1144 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001145 mpi X, Y, Z, T1, T2;
1146
1147 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001148 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001149
Paul Bakker6c591fa2011-05-05 11:49:20 +00001150 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1151 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001152
1153 if( mpi_cmp_abs( A, B ) < 0 )
1154 {
1155 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1156 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1157 return( 0 );
1158 }
1159
1160 MPI_CHK( mpi_copy( &X, A ) );
1161 MPI_CHK( mpi_copy( &Y, B ) );
1162 X.s = Y.s = 1;
1163
1164 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1165 MPI_CHK( mpi_lset( &Z, 0 ) );
1166 MPI_CHK( mpi_grow( &T1, 2 ) );
1167 MPI_CHK( mpi_grow( &T2, 3 ) );
1168
1169 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001170 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001171 {
1172 k = biL - 1 - k;
1173 MPI_CHK( mpi_shift_l( &X, k ) );
1174 MPI_CHK( mpi_shift_l( &Y, k ) );
1175 }
1176 else k = 0;
1177
1178 n = X.n - 1;
1179 t = Y.n - 1;
Paul Bakkerc110d022012-10-19 12:15:08 +00001180 MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001181
1182 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1183 {
1184 Z.p[n - t]++;
1185 mpi_sub_mpi( &X, &X, &Y );
1186 }
1187 mpi_shift_r( &Y, biL * (n - t) );
1188
1189 for( i = n; i > t ; i-- )
1190 {
1191 if( X.p[i] >= Y.p[t] )
1192 Z.p[i - t - 1] = ~0;
1193 else
1194 {
Paul Bakker62261d62012-10-02 12:19:31 +00001195#if defined(POLARSSL_HAVE_UDBL)
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001196 t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001197
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001198 r = (t_udbl) X.p[i] << biL;
1199 r |= (t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001200 r /= Y.p[t];
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001201 if( r > ((t_udbl) 1 << biL) - 1)
1202 r = ((t_udbl) 1 << biL) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001203
Paul Bakkera755ca12011-04-24 09:11:17 +00001204 Z.p[i - t - 1] = (t_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001205#else
1206 /*
1207 * __udiv_qrnnd_c, from gmp/longlong.h
1208 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001209 t_uint q0, q1, r0, r1;
1210 t_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001211
1212 d = Y.p[t];
1213 d0 = ( d << biH ) >> biH;
1214 d1 = ( d >> biH );
1215
1216 q1 = X.p[i] / d1;
1217 r1 = X.p[i] - d1 * q1;
1218 r1 <<= biH;
1219 r1 |= ( X.p[i - 1] >> biH );
1220
1221 m = q1 * d0;
1222 if( r1 < m )
1223 {
1224 q1--, r1 += d;
1225 while( r1 >= d && r1 < m )
1226 q1--, r1 += d;
1227 }
1228 r1 -= m;
1229
1230 q0 = r1 / d1;
1231 r0 = r1 - d1 * q0;
1232 r0 <<= biH;
1233 r0 |= ( X.p[i - 1] << biH ) >> biH;
1234
1235 m = q0 * d0;
1236 if( r0 < m )
1237 {
1238 q0--, r0 += d;
1239 while( r0 >= d && r0 < m )
1240 q0--, r0 += d;
1241 }
1242 r0 -= m;
1243
1244 Z.p[i - t - 1] = ( q1 << biH ) | q0;
1245#endif
1246 }
1247
1248 Z.p[i - t - 1]++;
1249 do
1250 {
1251 Z.p[i - t - 1]--;
1252
1253 MPI_CHK( mpi_lset( &T1, 0 ) );
1254 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1255 T1.p[1] = Y.p[t];
1256 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1257
1258 MPI_CHK( mpi_lset( &T2, 0 ) );
1259 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1260 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1261 T2.p[2] = X.p[i];
1262 }
1263 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1264
1265 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1266 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1267 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1268
1269 if( mpi_cmp_int( &X, 0 ) < 0 )
1270 {
1271 MPI_CHK( mpi_copy( &T1, &Y ) );
1272 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1273 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1274 Z.p[i - t - 1]--;
1275 }
1276 }
1277
1278 if( Q != NULL )
1279 {
1280 mpi_copy( Q, &Z );
1281 Q->s = A->s * B->s;
1282 }
1283
1284 if( R != NULL )
1285 {
1286 mpi_shift_r( &X, k );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001287 X.s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001288 mpi_copy( R, &X );
1289
Paul Bakker5121ce52009-01-03 21:22:43 +00001290 if( mpi_cmp_int( R, 0 ) == 0 )
1291 R->s = 1;
1292 }
1293
1294cleanup:
1295
Paul Bakker6c591fa2011-05-05 11:49:20 +00001296 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1297 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001298
1299 return( ret );
1300}
1301
1302/*
1303 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001304 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001305int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001306{
1307 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001308 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001309
1310 p[0] = ( b < 0 ) ? -b : b;
1311 _B.s = ( b < 0 ) ? -1 : 1;
1312 _B.n = 1;
1313 _B.p = p;
1314
1315 return( mpi_div_mpi( Q, R, A, &_B ) );
1316}
1317
1318/*
1319 * Modulo: R = A mod B
1320 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001321int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001322{
1323 int ret;
1324
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001325 if( mpi_cmp_int( B, 0 ) < 0 )
1326 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1327
Paul Bakker5121ce52009-01-03 21:22:43 +00001328 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1329
1330 while( mpi_cmp_int( R, 0 ) < 0 )
1331 MPI_CHK( mpi_add_mpi( R, R, B ) );
1332
1333 while( mpi_cmp_mpi( R, B ) >= 0 )
1334 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1335
1336cleanup:
1337
1338 return( ret );
1339}
1340
1341/*
1342 * Modulo: r = A mod b
1343 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001344int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001345{
Paul Bakker23986e52011-04-24 08:57:21 +00001346 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001347 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001348
1349 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001350 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001351
1352 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001353 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001354
1355 /*
1356 * handle trivial cases
1357 */
1358 if( b == 1 )
1359 {
1360 *r = 0;
1361 return( 0 );
1362 }
1363
1364 if( b == 2 )
1365 {
1366 *r = A->p[0] & 1;
1367 return( 0 );
1368 }
1369
1370 /*
1371 * general case
1372 */
Paul Bakker23986e52011-04-24 08:57:21 +00001373 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001374 {
Paul Bakker23986e52011-04-24 08:57:21 +00001375 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001376 y = ( y << biH ) | ( x >> biH );
1377 z = y / b;
1378 y -= z * b;
1379
1380 x <<= biH;
1381 y = ( y << biH ) | ( x >> biH );
1382 z = y / b;
1383 y -= z * b;
1384 }
1385
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001386 /*
1387 * If A is negative, then the current y represents a negative value.
1388 * Flipping it to the positive side.
1389 */
1390 if( A->s < 0 && y != 0 )
1391 y = b - y;
1392
Paul Bakker5121ce52009-01-03 21:22:43 +00001393 *r = y;
1394
1395 return( 0 );
1396}
1397
1398/*
1399 * Fast Montgomery initialization (thanks to Tom St Denis)
1400 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001401static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001402{
Paul Bakkera755ca12011-04-24 09:11:17 +00001403 t_uint x, m0 = N->p[0];
Paul Bakker5121ce52009-01-03 21:22:43 +00001404
1405 x = m0;
1406 x += ( ( m0 + 2 ) & 4 ) << 1;
1407 x *= ( 2 - ( m0 * x ) );
1408
1409 if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
1410 if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
1411 if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
1412
1413 *mm = ~x + 1;
1414}
1415
1416/*
1417 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1418 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001419static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001420{
Paul Bakker23986e52011-04-24 08:57:21 +00001421 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001422 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001423
1424 memset( T->p, 0, T->n * ciL );
1425
1426 d = T->p;
1427 n = N->n;
1428 m = ( B->n < n ) ? B->n : n;
1429
1430 for( i = 0; i < n; i++ )
1431 {
1432 /*
1433 * T = (T + u0*B + u1*N) / 2^biL
1434 */
1435 u0 = A->p[i];
1436 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1437
1438 mpi_mul_hlp( m, B->p, d, u0 );
1439 mpi_mul_hlp( n, N->p, d, u1 );
1440
1441 *d++ = u0; d[n + 1] = 0;
1442 }
1443
1444 memcpy( A->p, d, (n + 1) * ciL );
1445
1446 if( mpi_cmp_abs( A, N ) >= 0 )
1447 mpi_sub_hlp( n, N->p, A->p );
1448 else
1449 /* prevent timing attacks */
1450 mpi_sub_hlp( n, A->p, T->p );
1451}
1452
1453/*
1454 * Montgomery reduction: A = A * R^-1 mod N
1455 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001456static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001457{
Paul Bakkera755ca12011-04-24 09:11:17 +00001458 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001459 mpi U;
1460
Paul Bakker8ddb6452013-02-27 14:56:33 +01001461 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001462 U.p = &z;
1463
1464 mpi_montmul( A, &U, N, mm, T );
1465}
1466
1467/*
1468 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1469 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001470int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001471{
Paul Bakker23986e52011-04-24 08:57:21 +00001472 int ret;
1473 size_t wbits, wsize, one = 1;
1474 size_t i, j, nblimbs;
1475 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001476 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001477 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1478 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001479
1480 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001481 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001482
Paul Bakkerf6198c12012-05-16 08:02:29 +00001483 if( mpi_cmp_int( E, 0 ) < 0 )
1484 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1485
1486 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001487 * Init temps and window size
1488 */
1489 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001490 mpi_init( &RR ); mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001491 memset( W, 0, sizeof( W ) );
1492
1493 i = mpi_msb( E );
1494
1495 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1496 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1497
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001498 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1499 wsize = POLARSSL_MPI_WINDOW_SIZE;
1500
Paul Bakker5121ce52009-01-03 21:22:43 +00001501 j = N->n + 1;
1502 MPI_CHK( mpi_grow( X, j ) );
1503 MPI_CHK( mpi_grow( &W[1], j ) );
1504 MPI_CHK( mpi_grow( &T, j * 2 ) );
1505
1506 /*
Paul Bakker50546922012-05-19 08:40:49 +00001507 * Compensate for negative A (and correct at the end)
1508 */
1509 neg = ( A->s == -1 );
1510
1511 mpi_init( &Apos );
1512 if( neg )
1513 {
1514 MPI_CHK( mpi_copy( &Apos, A ) );
1515 Apos.s = 1;
1516 A = &Apos;
1517 }
1518
1519 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001520 * If 1st call, pre-compute R^2 mod N
1521 */
1522 if( _RR == NULL || _RR->p == NULL )
1523 {
1524 MPI_CHK( mpi_lset( &RR, 1 ) );
1525 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1526 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1527
1528 if( _RR != NULL )
1529 memcpy( _RR, &RR, sizeof( mpi ) );
1530 }
1531 else
1532 memcpy( &RR, _RR, sizeof( mpi ) );
1533
1534 /*
1535 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1536 */
1537 if( mpi_cmp_mpi( A, N ) >= 0 )
1538 mpi_mod_mpi( &W[1], A, N );
1539 else mpi_copy( &W[1], A );
1540
1541 mpi_montmul( &W[1], &RR, N, mm, &T );
1542
1543 /*
1544 * X = R^2 * R^-1 mod N = R mod N
1545 */
1546 MPI_CHK( mpi_copy( X, &RR ) );
1547 mpi_montred( X, N, mm, &T );
1548
1549 if( wsize > 1 )
1550 {
1551 /*
1552 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1553 */
Paul Bakker23986e52011-04-24 08:57:21 +00001554 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001555
1556 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1557 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1558
1559 for( i = 0; i < wsize - 1; i++ )
1560 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001561
Paul Bakker5121ce52009-01-03 21:22:43 +00001562 /*
1563 * W[i] = W[i - 1] * W[1]
1564 */
Paul Bakker23986e52011-04-24 08:57:21 +00001565 for( i = j + 1; i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001566 {
1567 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1568 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1569
1570 mpi_montmul( &W[i], &W[1], N, mm, &T );
1571 }
1572 }
1573
1574 nblimbs = E->n;
1575 bufsize = 0;
1576 nbits = 0;
1577 wbits = 0;
1578 state = 0;
1579
1580 while( 1 )
1581 {
1582 if( bufsize == 0 )
1583 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001584 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001585 break;
1586
Paul Bakker0d7702c2013-10-29 16:18:35 +01001587 nblimbs--;
1588
Paul Bakkera755ca12011-04-24 09:11:17 +00001589 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001590 }
1591
1592 bufsize--;
1593
1594 ei = (E->p[nblimbs] >> bufsize) & 1;
1595
1596 /*
1597 * skip leading 0s
1598 */
1599 if( ei == 0 && state == 0 )
1600 continue;
1601
1602 if( ei == 0 && state == 1 )
1603 {
1604 /*
1605 * out of window, square X
1606 */
1607 mpi_montmul( X, X, N, mm, &T );
1608 continue;
1609 }
1610
1611 /*
1612 * add ei to current window
1613 */
1614 state = 2;
1615
1616 nbits++;
1617 wbits |= (ei << (wsize - nbits));
1618
1619 if( nbits == wsize )
1620 {
1621 /*
1622 * X = X^wsize R^-1 mod N
1623 */
1624 for( i = 0; i < wsize; i++ )
1625 mpi_montmul( X, X, N, mm, &T );
1626
1627 /*
1628 * X = X * W[wbits] R^-1 mod N
1629 */
1630 mpi_montmul( X, &W[wbits], N, mm, &T );
1631
1632 state--;
1633 nbits = 0;
1634 wbits = 0;
1635 }
1636 }
1637
1638 /*
1639 * process the remaining bits
1640 */
1641 for( i = 0; i < nbits; i++ )
1642 {
1643 mpi_montmul( X, X, N, mm, &T );
1644
1645 wbits <<= 1;
1646
Paul Bakker23986e52011-04-24 08:57:21 +00001647 if( (wbits & (one << wsize)) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001648 mpi_montmul( X, &W[1], N, mm, &T );
1649 }
1650
1651 /*
1652 * X = A^E * R * R^-1 mod N = A^E mod N
1653 */
1654 mpi_montred( X, N, mm, &T );
1655
Paul Bakkerf6198c12012-05-16 08:02:29 +00001656 if( neg )
1657 {
1658 X->s = -1;
1659 mpi_add_mpi( X, N, X );
1660 }
1661
Paul Bakker5121ce52009-01-03 21:22:43 +00001662cleanup:
1663
Paul Bakker23986e52011-04-24 08:57:21 +00001664 for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001665 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001666
Paul Bakkerf6198c12012-05-16 08:02:29 +00001667 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001668
1669 if( _RR == NULL )
1670 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001671
1672 return( ret );
1673}
1674
Paul Bakker5121ce52009-01-03 21:22:43 +00001675/*
1676 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1677 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001678int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001679{
Paul Bakker23986e52011-04-24 08:57:21 +00001680 int ret;
1681 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001682 mpi TG, TA, TB;
1683
Paul Bakker6c591fa2011-05-05 11:49:20 +00001684 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001685
Paul Bakker5121ce52009-01-03 21:22:43 +00001686 MPI_CHK( mpi_copy( &TA, A ) );
1687 MPI_CHK( mpi_copy( &TB, B ) );
1688
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001689 lz = mpi_lsb( &TA );
1690 lzt = mpi_lsb( &TB );
1691
1692 if ( lzt < lz )
1693 lz = lzt;
1694
1695 MPI_CHK( mpi_shift_r( &TA, lz ) );
1696 MPI_CHK( mpi_shift_r( &TB, lz ) );
1697
Paul Bakker5121ce52009-01-03 21:22:43 +00001698 TA.s = TB.s = 1;
1699
1700 while( mpi_cmp_int( &TA, 0 ) != 0 )
1701 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001702 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1703 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001704
1705 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1706 {
1707 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1708 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1709 }
1710 else
1711 {
1712 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1713 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1714 }
1715 }
1716
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001717 MPI_CHK( mpi_shift_l( &TB, lz ) );
1718 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001719
1720cleanup:
1721
Paul Bakker6c591fa2011-05-05 11:49:20 +00001722 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001723
1724 return( ret );
1725}
1726
Paul Bakkera3d195c2011-11-27 21:07:34 +00001727int mpi_fill_random( mpi *X, size_t size,
1728 int (*f_rng)(void *, unsigned char *, size_t),
1729 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001730{
Paul Bakker23986e52011-04-24 08:57:21 +00001731 int ret;
Paul Bakker287781a2011-03-26 13:18:49 +00001732
Paul Bakker39dfdac2012-02-12 17:17:27 +00001733 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001734 MPI_CHK( mpi_lset( X, 0 ) );
1735
Paul Bakker39dfdac2012-02-12 17:17:27 +00001736 MPI_CHK( f_rng( p_rng, (unsigned char *) X->p, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001737
1738cleanup:
1739 return( ret );
1740}
1741
Paul Bakker5121ce52009-01-03 21:22:43 +00001742/*
1743 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1744 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001745int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001746{
1747 int ret;
1748 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1749
1750 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001751 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001752
Paul Bakker6c591fa2011-05-05 11:49:20 +00001753 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1754 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1755 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001756
1757 MPI_CHK( mpi_gcd( &G, A, N ) );
1758
1759 if( mpi_cmp_int( &G, 1 ) != 0 )
1760 {
Paul Bakker40e46942009-01-03 21:51:57 +00001761 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001762 goto cleanup;
1763 }
1764
1765 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1766 MPI_CHK( mpi_copy( &TU, &TA ) );
1767 MPI_CHK( mpi_copy( &TB, N ) );
1768 MPI_CHK( mpi_copy( &TV, N ) );
1769
1770 MPI_CHK( mpi_lset( &U1, 1 ) );
1771 MPI_CHK( mpi_lset( &U2, 0 ) );
1772 MPI_CHK( mpi_lset( &V1, 0 ) );
1773 MPI_CHK( mpi_lset( &V2, 1 ) );
1774
1775 do
1776 {
1777 while( ( TU.p[0] & 1 ) == 0 )
1778 {
1779 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1780
1781 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1782 {
1783 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1784 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1785 }
1786
1787 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1788 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1789 }
1790
1791 while( ( TV.p[0] & 1 ) == 0 )
1792 {
1793 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1794
1795 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1796 {
1797 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1798 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1799 }
1800
1801 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1802 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1803 }
1804
1805 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1806 {
1807 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1808 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1809 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1810 }
1811 else
1812 {
1813 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1814 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1815 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1816 }
1817 }
1818 while( mpi_cmp_int( &TU, 0 ) != 0 );
1819
1820 while( mpi_cmp_int( &V1, 0 ) < 0 )
1821 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1822
1823 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1824 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1825
1826 MPI_CHK( mpi_copy( X, &V1 ) );
1827
1828cleanup:
1829
Paul Bakker6c591fa2011-05-05 11:49:20 +00001830 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1831 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1832 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001833
1834 return( ret );
1835}
1836
Paul Bakkerd9374b02012-11-02 11:02:58 +00001837#if defined(POLARSSL_GENPRIME)
1838
Paul Bakker5121ce52009-01-03 21:22:43 +00001839static const int small_prime[] =
1840{
1841 3, 5, 7, 11, 13, 17, 19, 23,
1842 29, 31, 37, 41, 43, 47, 53, 59,
1843 61, 67, 71, 73, 79, 83, 89, 97,
1844 101, 103, 107, 109, 113, 127, 131, 137,
1845 139, 149, 151, 157, 163, 167, 173, 179,
1846 181, 191, 193, 197, 199, 211, 223, 227,
1847 229, 233, 239, 241, 251, 257, 263, 269,
1848 271, 277, 281, 283, 293, 307, 311, 313,
1849 317, 331, 337, 347, 349, 353, 359, 367,
1850 373, 379, 383, 389, 397, 401, 409, 419,
1851 421, 431, 433, 439, 443, 449, 457, 461,
1852 463, 467, 479, 487, 491, 499, 503, 509,
1853 521, 523, 541, 547, 557, 563, 569, 571,
1854 577, 587, 593, 599, 601, 607, 613, 617,
1855 619, 631, 641, 643, 647, 653, 659, 661,
1856 673, 677, 683, 691, 701, 709, 719, 727,
1857 733, 739, 743, 751, 757, 761, 769, 773,
1858 787, 797, 809, 811, 821, 823, 827, 829,
1859 839, 853, 857, 859, 863, 877, 881, 883,
1860 887, 907, 911, 919, 929, 937, 941, 947,
1861 953, 967, 971, 977, 983, 991, 997, -103
1862};
1863
1864/*
1865 * Miller-Rabin primality test (HAC 4.24)
1866 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001867int mpi_is_prime( mpi *X,
1868 int (*f_rng)(void *, unsigned char *, size_t),
1869 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001870{
Paul Bakker23986e52011-04-24 08:57:21 +00001871 int ret, xs;
1872 size_t i, j, n, s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001873 mpi W, R, T, A, RR;
Paul Bakker5121ce52009-01-03 21:22:43 +00001874
Paul Bakker48eab262009-06-25 21:25:49 +00001875 if( mpi_cmp_int( X, 0 ) == 0 ||
1876 mpi_cmp_int( X, 1 ) == 0 )
1877 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1878
1879 if( mpi_cmp_int( X, 2 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001880 return( 0 );
1881
Paul Bakker6c591fa2011-05-05 11:49:20 +00001882 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
1883 mpi_init( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001884
1885 xs = X->s; X->s = 1;
1886
1887 /*
1888 * test trivial factors first
1889 */
1890 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001891 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001892
1893 for( i = 0; small_prime[i] > 0; i++ )
1894 {
Paul Bakkera755ca12011-04-24 09:11:17 +00001895 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001896
1897 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
1898 return( 0 );
1899
1900 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1901
1902 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001903 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001904 }
1905
1906 /*
1907 * W = |X| - 1
1908 * R = W >> lsb( W )
1909 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001910 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001911 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001912 MPI_CHK( mpi_copy( &R, &W ) );
1913 MPI_CHK( mpi_shift_r( &R, s ) );
1914
1915 i = mpi_msb( X );
1916 /*
1917 * HAC, table 4.4
1918 */
1919 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1920 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1921 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1922
1923 for( i = 0; i < n; i++ )
1924 {
1925 /*
1926 * pick a random A, 1 < A < |X| - 1
1927 */
Paul Bakker901c6562012-04-20 13:25:38 +00001928 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001929
Paul Bakkerb94081b2011-01-05 15:53:06 +00001930 if( mpi_cmp_mpi( &A, &W ) >= 0 )
1931 {
1932 j = mpi_msb( &A ) - mpi_msb( &W );
1933 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1934 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001935 A.p[0] |= 3;
1936
1937 /*
1938 * A = A^R mod |X|
1939 */
1940 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1941
1942 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1943 mpi_cmp_int( &A, 1 ) == 0 )
1944 continue;
1945
1946 j = 1;
1947 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1948 {
1949 /*
1950 * A = A * A mod |X|
1951 */
1952 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1953 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1954
1955 if( mpi_cmp_int( &A, 1 ) == 0 )
1956 break;
1957
1958 j++;
1959 }
1960
1961 /*
1962 * not prime if A != |X| - 1 or A == 1
1963 */
1964 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1965 mpi_cmp_int( &A, 1 ) == 0 )
1966 {
Paul Bakker40e46942009-01-03 21:51:57 +00001967 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001968 break;
1969 }
1970 }
1971
1972cleanup:
1973
1974 X->s = xs;
1975
Paul Bakker6c591fa2011-05-05 11:49:20 +00001976 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
1977 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001978
1979 return( ret );
1980}
1981
1982/*
1983 * Prime number generation
1984 */
Paul Bakker23986e52011-04-24 08:57:21 +00001985int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001986 int (*f_rng)(void *, unsigned char *, size_t),
1987 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001988{
Paul Bakker23986e52011-04-24 08:57:21 +00001989 int ret;
1990 size_t k, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001991 mpi Y;
1992
Paul Bakkerfe3256e2011-11-25 12:11:43 +00001993 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00001994 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001995
Paul Bakker6c591fa2011-05-05 11:49:20 +00001996 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001997
1998 n = BITS_TO_LIMBS( nbits );
1999
Paul Bakker901c6562012-04-20 13:25:38 +00002000 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002001
2002 k = mpi_msb( X );
2003 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
2004 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
2005
2006 X->p[0] |= 3;
2007
2008 if( dh_flag == 0 )
2009 {
2010 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
2011 {
Paul Bakker40e46942009-01-03 21:51:57 +00002012 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002013 goto cleanup;
2014
2015 MPI_CHK( mpi_add_int( X, X, 2 ) );
2016 }
2017 }
2018 else
2019 {
2020 MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
2021 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2022
2023 while( 1 )
2024 {
2025 if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
2026 {
2027 if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
2028 break;
2029
Paul Bakker40e46942009-01-03 21:51:57 +00002030 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002031 goto cleanup;
2032 }
2033
Paul Bakker40e46942009-01-03 21:51:57 +00002034 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002035 goto cleanup;
2036
2037 MPI_CHK( mpi_add_int( &Y, X, 1 ) );
2038 MPI_CHK( mpi_add_int( X, X, 2 ) );
2039 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2040 }
2041 }
2042
2043cleanup:
2044
Paul Bakker6c591fa2011-05-05 11:49:20 +00002045 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002046
2047 return( ret );
2048}
2049
Manuel Pégourié-Gonnarddf0142b2013-08-22 18:29:07 +02002050#endif /* POLARSSL_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002051
Paul Bakker40e46942009-01-03 21:51:57 +00002052#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002053
Paul Bakker23986e52011-04-24 08:57:21 +00002054#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002055
2056static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2057{
2058 { 693, 609, 21 },
2059 { 1764, 868, 28 },
2060 { 768454923, 542167814, 1 }
2061};
2062
Paul Bakker5121ce52009-01-03 21:22:43 +00002063/*
2064 * Checkup routine
2065 */
2066int mpi_self_test( int verbose )
2067{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002068 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002069 mpi A, E, N, X, Y, U, V;
2070
Paul Bakker6c591fa2011-05-05 11:49:20 +00002071 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2072 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002073
2074 MPI_CHK( mpi_read_string( &A, 16,
2075 "EFE021C2645FD1DC586E69184AF4A31E" \
2076 "D5F53E93B5F123FA41680867BA110131" \
2077 "944FE7952E2517337780CB0DB80E61AA" \
2078 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2079
2080 MPI_CHK( mpi_read_string( &E, 16,
2081 "B2E7EFD37075B9F03FF989C7C5051C20" \
2082 "34D2A323810251127E7BF8625A4F49A5" \
2083 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2084 "5B5C25763222FEFCCFC38B832366C29E" ) );
2085
2086 MPI_CHK( mpi_read_string( &N, 16,
2087 "0066A198186C18C10B2F5ED9B522752A" \
2088 "9830B69916E535C8F047518A889A43A5" \
2089 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2090
2091 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2092
2093 MPI_CHK( mpi_read_string( &U, 16,
2094 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2095 "9E857EA95A03512E2BAE7391688D264A" \
2096 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2097 "8001B72E848A38CAE1C65F78E56ABDEF" \
2098 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2099 "ECF677152EF804370C1A305CAF3B5BF1" \
2100 "30879B56C61DE584A0F53A2447A51E" ) );
2101
2102 if( verbose != 0 )
2103 printf( " MPI test #1 (mul_mpi): " );
2104
2105 if( mpi_cmp_mpi( &X, &U ) != 0 )
2106 {
2107 if( verbose != 0 )
2108 printf( "failed\n" );
2109
2110 return( 1 );
2111 }
2112
2113 if( verbose != 0 )
2114 printf( "passed\n" );
2115
2116 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2117
2118 MPI_CHK( mpi_read_string( &U, 16,
2119 "256567336059E52CAE22925474705F39A94" ) );
2120
2121 MPI_CHK( mpi_read_string( &V, 16,
2122 "6613F26162223DF488E9CD48CC132C7A" \
2123 "0AC93C701B001B092E4E5B9F73BCD27B" \
2124 "9EE50D0657C77F374E903CDFA4C642" ) );
2125
2126 if( verbose != 0 )
2127 printf( " MPI test #2 (div_mpi): " );
2128
2129 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2130 mpi_cmp_mpi( &Y, &V ) != 0 )
2131 {
2132 if( verbose != 0 )
2133 printf( "failed\n" );
2134
2135 return( 1 );
2136 }
2137
2138 if( verbose != 0 )
2139 printf( "passed\n" );
2140
2141 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2142
2143 MPI_CHK( mpi_read_string( &U, 16,
2144 "36E139AEA55215609D2816998ED020BB" \
2145 "BD96C37890F65171D948E9BC7CBAA4D9" \
2146 "325D24D6A3C12710F10A09FA08AB87" ) );
2147
2148 if( verbose != 0 )
2149 printf( " MPI test #3 (exp_mod): " );
2150
2151 if( mpi_cmp_mpi( &X, &U ) != 0 )
2152 {
2153 if( verbose != 0 )
2154 printf( "failed\n" );
2155
2156 return( 1 );
2157 }
2158
2159 if( verbose != 0 )
2160 printf( "passed\n" );
2161
2162 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2163
2164 MPI_CHK( mpi_read_string( &U, 16,
2165 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2166 "C3DBA76456363A10869622EAC2DD84EC" \
2167 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2168
2169 if( verbose != 0 )
2170 printf( " MPI test #4 (inv_mod): " );
2171
2172 if( mpi_cmp_mpi( &X, &U ) != 0 )
2173 {
2174 if( verbose != 0 )
2175 printf( "failed\n" );
2176
2177 return( 1 );
2178 }
2179
2180 if( verbose != 0 )
2181 printf( "passed\n" );
2182
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002183 if( verbose != 0 )
2184 printf( " MPI test #5 (simple gcd): " );
2185
2186 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2187 {
2188 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002189 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002190
Paul Bakker23986e52011-04-24 08:57:21 +00002191 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002192
Paul Bakker23986e52011-04-24 08:57:21 +00002193 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2194 {
2195 if( verbose != 0 )
2196 printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002197
Paul Bakker23986e52011-04-24 08:57:21 +00002198 return( 1 );
2199 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002200 }
2201
2202 if( verbose != 0 )
2203 printf( "passed\n" );
2204
Paul Bakker5121ce52009-01-03 21:22:43 +00002205cleanup:
2206
2207 if( ret != 0 && verbose != 0 )
2208 printf( "Unexpected error, return code = %08X\n", ret );
2209
Paul Bakker6c591fa2011-05-05 11:49:20 +00002210 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2211 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002212
2213 if( verbose != 0 )
2214 printf( "\n" );
2215
2216 return( ret );
2217}
2218
2219#endif
2220
2221#endif