blob: 9eceeba55f1b7196568c764e8f06ea39643e6471 [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
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100209 * about whether the assignment was made or not.
210 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100211 */
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100212int mpi_safe_cond_assign( mpi *X, const mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100213{
214 int ret = 0;
215 size_t i;
216
217 if( assign * ( 1 - assign ) != 0 )
218 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
219
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100220 if( Y->n > X->n )
221 MPI_CHK( mpi_grow( X, Y->n ) );
222
223 /* Do the conditional assign safely */
Manuel Pégourié-Gonnard3e3d2b82013-11-21 21:12:26 +0100224 X->s = X->s * (1 - assign) + Y->s * assign;
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100225 for( i = 0; i < Y->n; i++ )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100226 X->p[i] = X->p[i] * (1 - assign) + Y->p[i] * assign;
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100227 for( ; i < X->n; i++ )
228 X->p[i] *= (1 - assign);
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100229
230cleanup:
231 return( ret );
232}
233
234/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000235 * Set value from integer
236 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000237int mpi_lset( mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000238{
239 int ret;
240
241 MPI_CHK( mpi_grow( X, 1 ) );
242 memset( X->p, 0, X->n * ciL );
243
244 X->p[0] = ( z < 0 ) ? -z : z;
245 X->s = ( z < 0 ) ? -1 : 1;
246
247cleanup:
248
249 return( ret );
250}
251
252/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000253 * Get a specific bit
254 */
Paul Bakker6b906e52012-05-08 12:01:43 +0000255int mpi_get_bit( const mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000256{
257 if( X->n * biL <= pos )
258 return( 0 );
259
260 return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
261}
262
263/*
264 * Set a bit to a specific value of 0 or 1
265 */
266int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
267{
268 int ret = 0;
269 size_t off = pos / biL;
270 size_t idx = pos % biL;
271
272 if( val != 0 && val != 1 )
273 return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
274
275 if( X->n * biL <= pos )
276 {
277 if( val == 0 )
278 return ( 0 );
279
280 MPI_CHK( mpi_grow( X, off + 1 ) );
281 }
282
283 X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
284
285cleanup:
286
287 return( ret );
288}
289
290/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000291 * Return the number of least significant bits
292 */
Paul Bakker23986e52011-04-24 08:57:21 +0000293size_t mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000294{
Paul Bakker23986e52011-04-24 08:57:21 +0000295 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000296
297 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000298 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000299 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
300 return( count );
301
302 return( 0 );
303}
304
305/*
306 * Return the number of most significant bits
307 */
Paul Bakker23986e52011-04-24 08:57:21 +0000308size_t mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000309{
Paul Bakker23986e52011-04-24 08:57:21 +0000310 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000311
312 for( i = X->n - 1; i > 0; i-- )
313 if( X->p[i] != 0 )
314 break;
315
Paul Bakker23986e52011-04-24 08:57:21 +0000316 for( j = biL; j > 0; j-- )
317 if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000318 break;
319
Paul Bakker23986e52011-04-24 08:57:21 +0000320 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000321}
322
323/*
324 * Return the total size in bytes
325 */
Paul Bakker23986e52011-04-24 08:57:21 +0000326size_t mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000327{
328 return( ( mpi_msb( X ) + 7 ) >> 3 );
329}
330
331/*
332 * Convert an ASCII character to digit value
333 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000334static int mpi_get_digit( t_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000335{
336 *d = 255;
337
338 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
339 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
340 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
341
Paul Bakkera755ca12011-04-24 09:11:17 +0000342 if( *d >= (t_uint) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000343 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000344
345 return( 0 );
346}
347
348/*
349 * Import from an ASCII string
350 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000351int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000352{
Paul Bakker23986e52011-04-24 08:57:21 +0000353 int ret;
354 size_t i, j, slen, n;
Paul Bakkera755ca12011-04-24 09:11:17 +0000355 t_uint d;
Paul Bakker5121ce52009-01-03 21:22:43 +0000356 mpi T;
357
358 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000359 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000360
Paul Bakker6c591fa2011-05-05 11:49:20 +0000361 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000362
Paul Bakkerff60ee62010-03-16 21:09:09 +0000363 slen = strlen( s );
364
Paul Bakker5121ce52009-01-03 21:22:43 +0000365 if( radix == 16 )
366 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000367 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000368
369 MPI_CHK( mpi_grow( X, n ) );
370 MPI_CHK( mpi_lset( X, 0 ) );
371
Paul Bakker23986e52011-04-24 08:57:21 +0000372 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000373 {
Paul Bakker23986e52011-04-24 08:57:21 +0000374 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000375 {
376 X->s = -1;
377 break;
378 }
379
Paul Bakker23986e52011-04-24 08:57:21 +0000380 MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000381 X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
382 }
383 }
384 else
385 {
386 MPI_CHK( mpi_lset( X, 0 ) );
387
Paul Bakkerff60ee62010-03-16 21:09:09 +0000388 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000389 {
390 if( i == 0 && s[i] == '-' )
391 {
392 X->s = -1;
393 continue;
394 }
395
396 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
397 MPI_CHK( mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000398
399 if( X->s == 1 )
400 {
401 MPI_CHK( mpi_add_int( X, &T, d ) );
402 }
403 else
404 {
405 MPI_CHK( mpi_sub_int( X, &T, d ) );
406 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000407 }
408 }
409
410cleanup:
411
Paul Bakker6c591fa2011-05-05 11:49:20 +0000412 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000413
414 return( ret );
415}
416
417/*
418 * Helper to write the digits high-order first
419 */
420static int mpi_write_hlp( mpi *X, int radix, char **p )
421{
422 int ret;
Paul Bakkera755ca12011-04-24 09:11:17 +0000423 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000424
425 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000426 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000427
428 MPI_CHK( mpi_mod_int( &r, X, radix ) );
429 MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
430
431 if( mpi_cmp_int( X, 0 ) != 0 )
432 MPI_CHK( mpi_write_hlp( X, radix, p ) );
433
434 if( r < 10 )
435 *(*p)++ = (char)( r + 0x30 );
436 else
437 *(*p)++ = (char)( r + 0x37 );
438
439cleanup:
440
441 return( ret );
442}
443
444/*
445 * Export into an ASCII string
446 */
Paul Bakker23986e52011-04-24 08:57:21 +0000447int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000448{
Paul Bakker23986e52011-04-24 08:57:21 +0000449 int ret = 0;
450 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000451 char *p;
452 mpi T;
453
454 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000455 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000456
457 n = mpi_msb( X );
458 if( radix >= 4 ) n >>= 1;
459 if( radix >= 16 ) n >>= 1;
460 n += 3;
461
462 if( *slen < n )
463 {
464 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000465 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000466 }
467
468 p = s;
Paul Bakker6c591fa2011-05-05 11:49:20 +0000469 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000470
471 if( X->s == -1 )
472 *p++ = '-';
473
474 if( radix == 16 )
475 {
Paul Bakker23986e52011-04-24 08:57:21 +0000476 int c;
477 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000478
Paul Bakker23986e52011-04-24 08:57:21 +0000479 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000480 {
Paul Bakker23986e52011-04-24 08:57:21 +0000481 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000482 {
Paul Bakker23986e52011-04-24 08:57:21 +0000483 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000484
Paul Bakker23986e52011-04-24 08:57:21 +0000485 if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000486 continue;
487
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000488 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000489 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000490 k = 1;
491 }
492 }
493 }
494 else
495 {
496 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000497
498 if( T.s == -1 )
499 T.s = 1;
500
Paul Bakker5121ce52009-01-03 21:22:43 +0000501 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
502 }
503
504 *p++ = '\0';
505 *slen = p - s;
506
507cleanup:
508
Paul Bakker6c591fa2011-05-05 11:49:20 +0000509 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000510
511 return( ret );
512}
513
Paul Bakker335db3f2011-04-25 15:28:35 +0000514#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000515/*
516 * Read X from an opened file
517 */
518int mpi_read_file( mpi *X, int radix, FILE *fin )
519{
Paul Bakkera755ca12011-04-24 09:11:17 +0000520 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000521 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000522 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000523 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000524 * Buffer should have space for (short) label and decimal formatted MPI,
525 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000526 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000527 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000528
529 memset( s, 0, sizeof( s ) );
530 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000531 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000532
533 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000534 if( slen == sizeof( s ) - 2 )
535 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
536
Paul Bakker5121ce52009-01-03 21:22:43 +0000537 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
538 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
539
540 p = s + slen;
541 while( --p >= s )
542 if( mpi_get_digit( &d, radix, *p ) != 0 )
543 break;
544
545 return( mpi_read_string( X, radix, p + 1 ) );
546}
547
548/*
549 * Write X into an opened file (or stdout if fout == NULL)
550 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000551int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000552{
Paul Bakker23986e52011-04-24 08:57:21 +0000553 int ret;
554 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000555 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000556 * Buffer should have space for (short) label and decimal formatted MPI,
557 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000558 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000559 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000560
561 n = sizeof( s );
562 memset( s, 0, n );
563 n -= 2;
564
Paul Bakker23986e52011-04-24 08:57:21 +0000565 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000566
567 if( p == NULL ) p = "";
568
569 plen = strlen( p );
570 slen = strlen( s );
571 s[slen++] = '\r';
572 s[slen++] = '\n';
573
574 if( fout != NULL )
575 {
576 if( fwrite( p, 1, plen, fout ) != plen ||
577 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000578 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000579 }
580 else
581 printf( "%s%s", p, s );
582
583cleanup:
584
585 return( ret );
586}
Paul Bakker335db3f2011-04-25 15:28:35 +0000587#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000588
589/*
590 * Import X from unsigned binary data, big endian
591 */
Paul Bakker23986e52011-04-24 08:57:21 +0000592int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000593{
Paul Bakker23986e52011-04-24 08:57:21 +0000594 int ret;
595 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000596
597 for( n = 0; n < buflen; n++ )
598 if( buf[n] != 0 )
599 break;
600
601 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
602 MPI_CHK( mpi_lset( X, 0 ) );
603
Paul Bakker23986e52011-04-24 08:57:21 +0000604 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000605 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000606
607cleanup:
608
609 return( ret );
610}
611
612/*
613 * Export X into unsigned binary data, big endian
614 */
Paul Bakker23986e52011-04-24 08:57:21 +0000615int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000616{
Paul Bakker23986e52011-04-24 08:57:21 +0000617 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000618
619 n = mpi_size( X );
620
621 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000622 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000623
624 memset( buf, 0, buflen );
625
626 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
627 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
628
629 return( 0 );
630}
631
632/*
633 * Left-shift: X <<= count
634 */
Paul Bakker23986e52011-04-24 08:57:21 +0000635int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000636{
Paul Bakker23986e52011-04-24 08:57:21 +0000637 int ret;
638 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000639 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000640
641 v0 = count / (biL );
642 t1 = count & (biL - 1);
643
644 i = mpi_msb( X ) + count;
645
Paul Bakkerf9688572011-05-05 10:00:45 +0000646 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000647 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
648
649 ret = 0;
650
651 /*
652 * shift by count / limb_size
653 */
654 if( v0 > 0 )
655 {
Paul Bakker23986e52011-04-24 08:57:21 +0000656 for( i = X->n; i > v0; i-- )
657 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000658
Paul Bakker23986e52011-04-24 08:57:21 +0000659 for( ; i > 0; i-- )
660 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000661 }
662
663 /*
664 * shift by count % limb_size
665 */
666 if( t1 > 0 )
667 {
668 for( i = v0; i < X->n; i++ )
669 {
670 r1 = X->p[i] >> (biL - t1);
671 X->p[i] <<= t1;
672 X->p[i] |= r0;
673 r0 = r1;
674 }
675 }
676
677cleanup:
678
679 return( ret );
680}
681
682/*
683 * Right-shift: X >>= count
684 */
Paul Bakker23986e52011-04-24 08:57:21 +0000685int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000686{
Paul Bakker23986e52011-04-24 08:57:21 +0000687 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000688 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000689
690 v0 = count / biL;
691 v1 = count & (biL - 1);
692
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100693 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
694 return mpi_lset( X, 0 );
695
Paul Bakker5121ce52009-01-03 21:22:43 +0000696 /*
697 * shift by count / limb_size
698 */
699 if( v0 > 0 )
700 {
701 for( i = 0; i < X->n - v0; i++ )
702 X->p[i] = X->p[i + v0];
703
704 for( ; i < X->n; i++ )
705 X->p[i] = 0;
706 }
707
708 /*
709 * shift by count % limb_size
710 */
711 if( v1 > 0 )
712 {
Paul Bakker23986e52011-04-24 08:57:21 +0000713 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000714 {
Paul Bakker23986e52011-04-24 08:57:21 +0000715 r1 = X->p[i - 1] << (biL - v1);
716 X->p[i - 1] >>= v1;
717 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000718 r0 = r1;
719 }
720 }
721
722 return( 0 );
723}
724
725/*
726 * Compare unsigned values
727 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000728int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000729{
Paul Bakker23986e52011-04-24 08:57:21 +0000730 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000731
Paul Bakker23986e52011-04-24 08:57:21 +0000732 for( i = X->n; i > 0; i-- )
733 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000734 break;
735
Paul Bakker23986e52011-04-24 08:57:21 +0000736 for( j = Y->n; j > 0; j-- )
737 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000738 break;
739
Paul Bakker23986e52011-04-24 08:57:21 +0000740 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000741 return( 0 );
742
743 if( i > j ) return( 1 );
744 if( j > i ) return( -1 );
745
Paul Bakker23986e52011-04-24 08:57:21 +0000746 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000747 {
Paul Bakker23986e52011-04-24 08:57:21 +0000748 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
749 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000750 }
751
752 return( 0 );
753}
754
755/*
756 * Compare signed values
757 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000758int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000759{
Paul Bakker23986e52011-04-24 08:57:21 +0000760 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000761
Paul Bakker23986e52011-04-24 08:57:21 +0000762 for( i = X->n; i > 0; i-- )
763 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000764 break;
765
Paul Bakker23986e52011-04-24 08:57:21 +0000766 for( j = Y->n; j > 0; j-- )
767 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000768 break;
769
Paul Bakker23986e52011-04-24 08:57:21 +0000770 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000771 return( 0 );
772
773 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000774 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000775
776 if( X->s > 0 && Y->s < 0 ) return( 1 );
777 if( Y->s > 0 && X->s < 0 ) return( -1 );
778
Paul Bakker23986e52011-04-24 08:57:21 +0000779 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000780 {
Paul Bakker23986e52011-04-24 08:57:21 +0000781 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
782 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000783 }
784
785 return( 0 );
786}
787
788/*
789 * Compare signed values
790 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000791int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000792{
793 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000794 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000795
796 *p = ( z < 0 ) ? -z : z;
797 Y.s = ( z < 0 ) ? -1 : 1;
798 Y.n = 1;
799 Y.p = p;
800
801 return( mpi_cmp_mpi( X, &Y ) );
802}
803
804/*
805 * Unsigned addition: X = |A| + |B| (HAC 14.7)
806 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000807int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000808{
Paul Bakker23986e52011-04-24 08:57:21 +0000809 int ret;
810 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000811 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000812
813 if( X == B )
814 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000815 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000816 }
817
818 if( X != A )
819 MPI_CHK( mpi_copy( X, A ) );
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000820
821 /*
822 * X should always be positive as a result of unsigned additions.
823 */
824 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000825
Paul Bakker23986e52011-04-24 08:57:21 +0000826 for( j = B->n; j > 0; j-- )
827 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000828 break;
829
Paul Bakker23986e52011-04-24 08:57:21 +0000830 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000831
832 o = B->p; p = X->p; c = 0;
833
Paul Bakker23986e52011-04-24 08:57:21 +0000834 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000835 {
836 *p += c; c = ( *p < c );
837 *p += *o; c += ( *p < *o );
838 }
839
840 while( c != 0 )
841 {
842 if( i >= X->n )
843 {
844 MPI_CHK( mpi_grow( X, i + 1 ) );
845 p = X->p + i;
846 }
847
Paul Bakker2d319fd2012-09-16 21:34:26 +0000848 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000849 }
850
851cleanup:
852
853 return( ret );
854}
855
856/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100857 * Helper for mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000858 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000859static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000860{
Paul Bakker23986e52011-04-24 08:57:21 +0000861 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000862 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000863
864 for( i = c = 0; i < n; i++, s++, d++ )
865 {
866 z = ( *d < c ); *d -= c;
867 c = ( *d < *s ) + z; *d -= *s;
868 }
869
870 while( c != 0 )
871 {
872 z = ( *d < c ); *d -= c;
873 c = z; i++; d++;
874 }
875}
876
877/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100878 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000879 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000880int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000881{
882 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000883 int ret;
884 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000885
886 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000887 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000888
Paul Bakker6c591fa2011-05-05 11:49:20 +0000889 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000890
891 if( X == B )
892 {
893 MPI_CHK( mpi_copy( &TB, B ) );
894 B = &TB;
895 }
896
897 if( X != A )
898 MPI_CHK( mpi_copy( X, A ) );
899
Paul Bakker1ef7a532009-06-20 10:50:55 +0000900 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100901 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000902 */
903 X->s = 1;
904
Paul Bakker5121ce52009-01-03 21:22:43 +0000905 ret = 0;
906
Paul Bakker23986e52011-04-24 08:57:21 +0000907 for( n = B->n; n > 0; n-- )
908 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000909 break;
910
Paul Bakker23986e52011-04-24 08:57:21 +0000911 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000912
913cleanup:
914
Paul Bakker6c591fa2011-05-05 11:49:20 +0000915 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000916
917 return( ret );
918}
919
920/*
921 * Signed addition: X = A + B
922 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000923int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000924{
925 int ret, s = A->s;
926
927 if( A->s * B->s < 0 )
928 {
929 if( mpi_cmp_abs( A, B ) >= 0 )
930 {
931 MPI_CHK( mpi_sub_abs( X, A, B ) );
932 X->s = s;
933 }
934 else
935 {
936 MPI_CHK( mpi_sub_abs( X, B, A ) );
937 X->s = -s;
938 }
939 }
940 else
941 {
942 MPI_CHK( mpi_add_abs( X, A, B ) );
943 X->s = s;
944 }
945
946cleanup:
947
948 return( ret );
949}
950
951/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100952 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +0000953 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000954int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000955{
956 int ret, s = A->s;
957
958 if( A->s * B->s > 0 )
959 {
960 if( mpi_cmp_abs( A, B ) >= 0 )
961 {
962 MPI_CHK( mpi_sub_abs( X, A, B ) );
963 X->s = s;
964 }
965 else
966 {
967 MPI_CHK( mpi_sub_abs( X, B, A ) );
968 X->s = -s;
969 }
970 }
971 else
972 {
973 MPI_CHK( mpi_add_abs( X, A, B ) );
974 X->s = s;
975 }
976
977cleanup:
978
979 return( ret );
980}
981
982/*
983 * Signed addition: X = A + b
984 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000985int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000986{
987 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000988 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000989
990 p[0] = ( b < 0 ) ? -b : b;
991 _B.s = ( b < 0 ) ? -1 : 1;
992 _B.n = 1;
993 _B.p = p;
994
995 return( mpi_add_mpi( X, A, &_B ) );
996}
997
998/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100999 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001000 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001001int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001002{
1003 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001004 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001005
1006 p[0] = ( b < 0 ) ? -b : b;
1007 _B.s = ( b < 0 ) ? -1 : 1;
1008 _B.n = 1;
1009 _B.p = p;
1010
1011 return( mpi_sub_mpi( X, A, &_B ) );
1012}
1013
1014/*
1015 * Helper for mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001016 */
1017static
1018#if defined(__APPLE__) && defined(__arm__)
1019/*
1020 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1021 * appears to need this to prevent bad ARM code generation at -O3.
1022 */
1023__attribute__ ((noinline))
1024#endif
1025void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001026{
Paul Bakkera755ca12011-04-24 09:11:17 +00001027 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001028
1029#if defined(MULADDC_HUIT)
1030 for( ; i >= 8; i -= 8 )
1031 {
1032 MULADDC_INIT
1033 MULADDC_HUIT
1034 MULADDC_STOP
1035 }
1036
1037 for( ; i > 0; i-- )
1038 {
1039 MULADDC_INIT
1040 MULADDC_CORE
1041 MULADDC_STOP
1042 }
1043#else
1044 for( ; i >= 16; i -= 16 )
1045 {
1046 MULADDC_INIT
1047 MULADDC_CORE MULADDC_CORE
1048 MULADDC_CORE MULADDC_CORE
1049 MULADDC_CORE MULADDC_CORE
1050 MULADDC_CORE MULADDC_CORE
1051
1052 MULADDC_CORE MULADDC_CORE
1053 MULADDC_CORE MULADDC_CORE
1054 MULADDC_CORE MULADDC_CORE
1055 MULADDC_CORE MULADDC_CORE
1056 MULADDC_STOP
1057 }
1058
1059 for( ; i >= 8; i -= 8 )
1060 {
1061 MULADDC_INIT
1062 MULADDC_CORE MULADDC_CORE
1063 MULADDC_CORE MULADDC_CORE
1064
1065 MULADDC_CORE MULADDC_CORE
1066 MULADDC_CORE MULADDC_CORE
1067 MULADDC_STOP
1068 }
1069
1070 for( ; i > 0; i-- )
1071 {
1072 MULADDC_INIT
1073 MULADDC_CORE
1074 MULADDC_STOP
1075 }
1076#endif
1077
1078 t++;
1079
1080 do {
1081 *d += c; c = ( *d < c ); d++;
1082 }
1083 while( c != 0 );
1084}
1085
1086/*
1087 * Baseline multiplication: X = A * B (HAC 14.12)
1088 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001089int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001090{
Paul Bakker23986e52011-04-24 08:57:21 +00001091 int ret;
1092 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001093 mpi TA, TB;
1094
Paul Bakker6c591fa2011-05-05 11:49:20 +00001095 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001096
1097 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1098 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1099
Paul Bakker23986e52011-04-24 08:57:21 +00001100 for( i = A->n; i > 0; i-- )
1101 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001102 break;
1103
Paul Bakker23986e52011-04-24 08:57:21 +00001104 for( j = B->n; j > 0; j-- )
1105 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001106 break;
1107
Paul Bakker23986e52011-04-24 08:57:21 +00001108 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001109 MPI_CHK( mpi_lset( X, 0 ) );
1110
Paul Bakker23986e52011-04-24 08:57:21 +00001111 for( i++; j > 0; j-- )
1112 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001113
1114 X->s = A->s * B->s;
1115
1116cleanup:
1117
Paul Bakker6c591fa2011-05-05 11:49:20 +00001118 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001119
1120 return( ret );
1121}
1122
1123/*
1124 * Baseline multiplication: X = A * b
1125 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001126int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001127{
1128 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001129 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001130
1131 _B.s = 1;
1132 _B.n = 1;
1133 _B.p = p;
1134 p[0] = b;
1135
1136 return( mpi_mul_mpi( X, A, &_B ) );
1137}
1138
1139/*
1140 * Division by mpi: A = Q * B + R (HAC 14.20)
1141 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001142int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001143{
Paul Bakker23986e52011-04-24 08:57:21 +00001144 int ret;
1145 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001146 mpi X, Y, Z, T1, T2;
1147
1148 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001149 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001150
Paul Bakker6c591fa2011-05-05 11:49:20 +00001151 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1152 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001153
1154 if( mpi_cmp_abs( A, B ) < 0 )
1155 {
1156 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1157 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1158 return( 0 );
1159 }
1160
1161 MPI_CHK( mpi_copy( &X, A ) );
1162 MPI_CHK( mpi_copy( &Y, B ) );
1163 X.s = Y.s = 1;
1164
1165 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1166 MPI_CHK( mpi_lset( &Z, 0 ) );
1167 MPI_CHK( mpi_grow( &T1, 2 ) );
1168 MPI_CHK( mpi_grow( &T2, 3 ) );
1169
1170 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001171 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001172 {
1173 k = biL - 1 - k;
1174 MPI_CHK( mpi_shift_l( &X, k ) );
1175 MPI_CHK( mpi_shift_l( &Y, k ) );
1176 }
1177 else k = 0;
1178
1179 n = X.n - 1;
1180 t = Y.n - 1;
Paul Bakkerc110d022012-10-19 12:15:08 +00001181 MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001182
1183 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1184 {
1185 Z.p[n - t]++;
1186 mpi_sub_mpi( &X, &X, &Y );
1187 }
1188 mpi_shift_r( &Y, biL * (n - t) );
1189
1190 for( i = n; i > t ; i-- )
1191 {
1192 if( X.p[i] >= Y.p[t] )
1193 Z.p[i - t - 1] = ~0;
1194 else
1195 {
Paul Bakker62261d62012-10-02 12:19:31 +00001196#if defined(POLARSSL_HAVE_UDBL)
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001197 t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001198
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001199 r = (t_udbl) X.p[i] << biL;
1200 r |= (t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001201 r /= Y.p[t];
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001202 if( r > ((t_udbl) 1 << biL) - 1)
1203 r = ((t_udbl) 1 << biL) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001204
Paul Bakkera755ca12011-04-24 09:11:17 +00001205 Z.p[i - t - 1] = (t_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001206#else
1207 /*
1208 * __udiv_qrnnd_c, from gmp/longlong.h
1209 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001210 t_uint q0, q1, r0, r1;
1211 t_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001212
1213 d = Y.p[t];
1214 d0 = ( d << biH ) >> biH;
1215 d1 = ( d >> biH );
1216
1217 q1 = X.p[i] / d1;
1218 r1 = X.p[i] - d1 * q1;
1219 r1 <<= biH;
1220 r1 |= ( X.p[i - 1] >> biH );
1221
1222 m = q1 * d0;
1223 if( r1 < m )
1224 {
1225 q1--, r1 += d;
1226 while( r1 >= d && r1 < m )
1227 q1--, r1 += d;
1228 }
1229 r1 -= m;
1230
1231 q0 = r1 / d1;
1232 r0 = r1 - d1 * q0;
1233 r0 <<= biH;
1234 r0 |= ( X.p[i - 1] << biH ) >> biH;
1235
1236 m = q0 * d0;
1237 if( r0 < m )
1238 {
1239 q0--, r0 += d;
1240 while( r0 >= d && r0 < m )
1241 q0--, r0 += d;
1242 }
1243 r0 -= m;
1244
1245 Z.p[i - t - 1] = ( q1 << biH ) | q0;
1246#endif
1247 }
1248
1249 Z.p[i - t - 1]++;
1250 do
1251 {
1252 Z.p[i - t - 1]--;
1253
1254 MPI_CHK( mpi_lset( &T1, 0 ) );
1255 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1256 T1.p[1] = Y.p[t];
1257 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1258
1259 MPI_CHK( mpi_lset( &T2, 0 ) );
1260 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1261 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1262 T2.p[2] = X.p[i];
1263 }
1264 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1265
1266 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1267 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1268 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1269
1270 if( mpi_cmp_int( &X, 0 ) < 0 )
1271 {
1272 MPI_CHK( mpi_copy( &T1, &Y ) );
1273 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1274 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1275 Z.p[i - t - 1]--;
1276 }
1277 }
1278
1279 if( Q != NULL )
1280 {
1281 mpi_copy( Q, &Z );
1282 Q->s = A->s * B->s;
1283 }
1284
1285 if( R != NULL )
1286 {
1287 mpi_shift_r( &X, k );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001288 X.s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001289 mpi_copy( R, &X );
1290
Paul Bakker5121ce52009-01-03 21:22:43 +00001291 if( mpi_cmp_int( R, 0 ) == 0 )
1292 R->s = 1;
1293 }
1294
1295cleanup:
1296
Paul Bakker6c591fa2011-05-05 11:49:20 +00001297 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1298 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001299
1300 return( ret );
1301}
1302
1303/*
1304 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001305 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001306int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001307{
1308 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001309 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001310
1311 p[0] = ( b < 0 ) ? -b : b;
1312 _B.s = ( b < 0 ) ? -1 : 1;
1313 _B.n = 1;
1314 _B.p = p;
1315
1316 return( mpi_div_mpi( Q, R, A, &_B ) );
1317}
1318
1319/*
1320 * Modulo: R = A mod B
1321 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001322int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001323{
1324 int ret;
1325
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001326 if( mpi_cmp_int( B, 0 ) < 0 )
1327 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1328
Paul Bakker5121ce52009-01-03 21:22:43 +00001329 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1330
1331 while( mpi_cmp_int( R, 0 ) < 0 )
1332 MPI_CHK( mpi_add_mpi( R, R, B ) );
1333
1334 while( mpi_cmp_mpi( R, B ) >= 0 )
1335 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1336
1337cleanup:
1338
1339 return( ret );
1340}
1341
1342/*
1343 * Modulo: r = A mod b
1344 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001345int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001346{
Paul Bakker23986e52011-04-24 08:57:21 +00001347 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001348 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001349
1350 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001351 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001352
1353 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001354 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001355
1356 /*
1357 * handle trivial cases
1358 */
1359 if( b == 1 )
1360 {
1361 *r = 0;
1362 return( 0 );
1363 }
1364
1365 if( b == 2 )
1366 {
1367 *r = A->p[0] & 1;
1368 return( 0 );
1369 }
1370
1371 /*
1372 * general case
1373 */
Paul Bakker23986e52011-04-24 08:57:21 +00001374 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001375 {
Paul Bakker23986e52011-04-24 08:57:21 +00001376 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001377 y = ( y << biH ) | ( x >> biH );
1378 z = y / b;
1379 y -= z * b;
1380
1381 x <<= biH;
1382 y = ( y << biH ) | ( x >> biH );
1383 z = y / b;
1384 y -= z * b;
1385 }
1386
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001387 /*
1388 * If A is negative, then the current y represents a negative value.
1389 * Flipping it to the positive side.
1390 */
1391 if( A->s < 0 && y != 0 )
1392 y = b - y;
1393
Paul Bakker5121ce52009-01-03 21:22:43 +00001394 *r = y;
1395
1396 return( 0 );
1397}
1398
1399/*
1400 * Fast Montgomery initialization (thanks to Tom St Denis)
1401 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001402static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001403{
Paul Bakkera755ca12011-04-24 09:11:17 +00001404 t_uint x, m0 = N->p[0];
Paul Bakker5121ce52009-01-03 21:22:43 +00001405
1406 x = m0;
1407 x += ( ( m0 + 2 ) & 4 ) << 1;
1408 x *= ( 2 - ( m0 * x ) );
1409
1410 if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
1411 if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
1412 if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
1413
1414 *mm = ~x + 1;
1415}
1416
1417/*
1418 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1419 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001420static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001421{
Paul Bakker23986e52011-04-24 08:57:21 +00001422 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001423 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001424
1425 memset( T->p, 0, T->n * ciL );
1426
1427 d = T->p;
1428 n = N->n;
1429 m = ( B->n < n ) ? B->n : n;
1430
1431 for( i = 0; i < n; i++ )
1432 {
1433 /*
1434 * T = (T + u0*B + u1*N) / 2^biL
1435 */
1436 u0 = A->p[i];
1437 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1438
1439 mpi_mul_hlp( m, B->p, d, u0 );
1440 mpi_mul_hlp( n, N->p, d, u1 );
1441
1442 *d++ = u0; d[n + 1] = 0;
1443 }
1444
1445 memcpy( A->p, d, (n + 1) * ciL );
1446
1447 if( mpi_cmp_abs( A, N ) >= 0 )
1448 mpi_sub_hlp( n, N->p, A->p );
1449 else
1450 /* prevent timing attacks */
1451 mpi_sub_hlp( n, A->p, T->p );
1452}
1453
1454/*
1455 * Montgomery reduction: A = A * R^-1 mod N
1456 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001457static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001458{
Paul Bakkera755ca12011-04-24 09:11:17 +00001459 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001460 mpi U;
1461
Paul Bakker8ddb6452013-02-27 14:56:33 +01001462 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001463 U.p = &z;
1464
1465 mpi_montmul( A, &U, N, mm, T );
1466}
1467
1468/*
1469 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1470 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001471int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001472{
Paul Bakker23986e52011-04-24 08:57:21 +00001473 int ret;
1474 size_t wbits, wsize, one = 1;
1475 size_t i, j, nblimbs;
1476 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001477 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001478 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1479 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001480
1481 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001482 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001483
Paul Bakkerf6198c12012-05-16 08:02:29 +00001484 if( mpi_cmp_int( E, 0 ) < 0 )
1485 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1486
1487 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001488 * Init temps and window size
1489 */
1490 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001491 mpi_init( &RR ); mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001492 memset( W, 0, sizeof( W ) );
1493
1494 i = mpi_msb( E );
1495
1496 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1497 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1498
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001499 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1500 wsize = POLARSSL_MPI_WINDOW_SIZE;
1501
Paul Bakker5121ce52009-01-03 21:22:43 +00001502 j = N->n + 1;
1503 MPI_CHK( mpi_grow( X, j ) );
1504 MPI_CHK( mpi_grow( &W[1], j ) );
1505 MPI_CHK( mpi_grow( &T, j * 2 ) );
1506
1507 /*
Paul Bakker50546922012-05-19 08:40:49 +00001508 * Compensate for negative A (and correct at the end)
1509 */
1510 neg = ( A->s == -1 );
1511
1512 mpi_init( &Apos );
1513 if( neg )
1514 {
1515 MPI_CHK( mpi_copy( &Apos, A ) );
1516 Apos.s = 1;
1517 A = &Apos;
1518 }
1519
1520 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001521 * If 1st call, pre-compute R^2 mod N
1522 */
1523 if( _RR == NULL || _RR->p == NULL )
1524 {
1525 MPI_CHK( mpi_lset( &RR, 1 ) );
1526 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1527 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1528
1529 if( _RR != NULL )
1530 memcpy( _RR, &RR, sizeof( mpi ) );
1531 }
1532 else
1533 memcpy( &RR, _RR, sizeof( mpi ) );
1534
1535 /*
1536 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1537 */
1538 if( mpi_cmp_mpi( A, N ) >= 0 )
1539 mpi_mod_mpi( &W[1], A, N );
1540 else mpi_copy( &W[1], A );
1541
1542 mpi_montmul( &W[1], &RR, N, mm, &T );
1543
1544 /*
1545 * X = R^2 * R^-1 mod N = R mod N
1546 */
1547 MPI_CHK( mpi_copy( X, &RR ) );
1548 mpi_montred( X, N, mm, &T );
1549
1550 if( wsize > 1 )
1551 {
1552 /*
1553 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1554 */
Paul Bakker23986e52011-04-24 08:57:21 +00001555 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001556
1557 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1558 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1559
1560 for( i = 0; i < wsize - 1; i++ )
1561 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001562
Paul Bakker5121ce52009-01-03 21:22:43 +00001563 /*
1564 * W[i] = W[i - 1] * W[1]
1565 */
Paul Bakker23986e52011-04-24 08:57:21 +00001566 for( i = j + 1; i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001567 {
1568 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1569 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1570
1571 mpi_montmul( &W[i], &W[1], N, mm, &T );
1572 }
1573 }
1574
1575 nblimbs = E->n;
1576 bufsize = 0;
1577 nbits = 0;
1578 wbits = 0;
1579 state = 0;
1580
1581 while( 1 )
1582 {
1583 if( bufsize == 0 )
1584 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001585 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001586 break;
1587
Paul Bakker0d7702c2013-10-29 16:18:35 +01001588 nblimbs--;
1589
Paul Bakkera755ca12011-04-24 09:11:17 +00001590 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001591 }
1592
1593 bufsize--;
1594
1595 ei = (E->p[nblimbs] >> bufsize) & 1;
1596
1597 /*
1598 * skip leading 0s
1599 */
1600 if( ei == 0 && state == 0 )
1601 continue;
1602
1603 if( ei == 0 && state == 1 )
1604 {
1605 /*
1606 * out of window, square X
1607 */
1608 mpi_montmul( X, X, N, mm, &T );
1609 continue;
1610 }
1611
1612 /*
1613 * add ei to current window
1614 */
1615 state = 2;
1616
1617 nbits++;
1618 wbits |= (ei << (wsize - nbits));
1619
1620 if( nbits == wsize )
1621 {
1622 /*
1623 * X = X^wsize R^-1 mod N
1624 */
1625 for( i = 0; i < wsize; i++ )
1626 mpi_montmul( X, X, N, mm, &T );
1627
1628 /*
1629 * X = X * W[wbits] R^-1 mod N
1630 */
1631 mpi_montmul( X, &W[wbits], N, mm, &T );
1632
1633 state--;
1634 nbits = 0;
1635 wbits = 0;
1636 }
1637 }
1638
1639 /*
1640 * process the remaining bits
1641 */
1642 for( i = 0; i < nbits; i++ )
1643 {
1644 mpi_montmul( X, X, N, mm, &T );
1645
1646 wbits <<= 1;
1647
Paul Bakker23986e52011-04-24 08:57:21 +00001648 if( (wbits & (one << wsize)) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001649 mpi_montmul( X, &W[1], N, mm, &T );
1650 }
1651
1652 /*
1653 * X = A^E * R * R^-1 mod N = A^E mod N
1654 */
1655 mpi_montred( X, N, mm, &T );
1656
Paul Bakkerf6198c12012-05-16 08:02:29 +00001657 if( neg )
1658 {
1659 X->s = -1;
1660 mpi_add_mpi( X, N, X );
1661 }
1662
Paul Bakker5121ce52009-01-03 21:22:43 +00001663cleanup:
1664
Paul Bakker23986e52011-04-24 08:57:21 +00001665 for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001666 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001667
Paul Bakkerf6198c12012-05-16 08:02:29 +00001668 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001669
1670 if( _RR == NULL )
1671 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001672
1673 return( ret );
1674}
1675
Paul Bakker5121ce52009-01-03 21:22:43 +00001676/*
1677 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1678 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001679int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001680{
Paul Bakker23986e52011-04-24 08:57:21 +00001681 int ret;
1682 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001683 mpi TG, TA, TB;
1684
Paul Bakker6c591fa2011-05-05 11:49:20 +00001685 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001686
Paul Bakker5121ce52009-01-03 21:22:43 +00001687 MPI_CHK( mpi_copy( &TA, A ) );
1688 MPI_CHK( mpi_copy( &TB, B ) );
1689
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001690 lz = mpi_lsb( &TA );
1691 lzt = mpi_lsb( &TB );
1692
1693 if ( lzt < lz )
1694 lz = lzt;
1695
1696 MPI_CHK( mpi_shift_r( &TA, lz ) );
1697 MPI_CHK( mpi_shift_r( &TB, lz ) );
1698
Paul Bakker5121ce52009-01-03 21:22:43 +00001699 TA.s = TB.s = 1;
1700
1701 while( mpi_cmp_int( &TA, 0 ) != 0 )
1702 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001703 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1704 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001705
1706 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1707 {
1708 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1709 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1710 }
1711 else
1712 {
1713 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1714 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1715 }
1716 }
1717
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001718 MPI_CHK( mpi_shift_l( &TB, lz ) );
1719 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001720
1721cleanup:
1722
Paul Bakker6c591fa2011-05-05 11:49:20 +00001723 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001724
1725 return( ret );
1726}
1727
Paul Bakkera3d195c2011-11-27 21:07:34 +00001728int mpi_fill_random( mpi *X, size_t size,
1729 int (*f_rng)(void *, unsigned char *, size_t),
1730 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001731{
Paul Bakker23986e52011-04-24 08:57:21 +00001732 int ret;
Paul Bakker287781a2011-03-26 13:18:49 +00001733
Paul Bakker39dfdac2012-02-12 17:17:27 +00001734 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001735 MPI_CHK( mpi_lset( X, 0 ) );
1736
Paul Bakker39dfdac2012-02-12 17:17:27 +00001737 MPI_CHK( f_rng( p_rng, (unsigned char *) X->p, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001738
1739cleanup:
1740 return( ret );
1741}
1742
Paul Bakker5121ce52009-01-03 21:22:43 +00001743/*
1744 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1745 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001746int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001747{
1748 int ret;
1749 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1750
1751 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001752 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001753
Paul Bakker6c591fa2011-05-05 11:49:20 +00001754 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1755 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1756 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001757
1758 MPI_CHK( mpi_gcd( &G, A, N ) );
1759
1760 if( mpi_cmp_int( &G, 1 ) != 0 )
1761 {
Paul Bakker40e46942009-01-03 21:51:57 +00001762 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001763 goto cleanup;
1764 }
1765
1766 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1767 MPI_CHK( mpi_copy( &TU, &TA ) );
1768 MPI_CHK( mpi_copy( &TB, N ) );
1769 MPI_CHK( mpi_copy( &TV, N ) );
1770
1771 MPI_CHK( mpi_lset( &U1, 1 ) );
1772 MPI_CHK( mpi_lset( &U2, 0 ) );
1773 MPI_CHK( mpi_lset( &V1, 0 ) );
1774 MPI_CHK( mpi_lset( &V2, 1 ) );
1775
1776 do
1777 {
1778 while( ( TU.p[0] & 1 ) == 0 )
1779 {
1780 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1781
1782 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1783 {
1784 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1785 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1786 }
1787
1788 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1789 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1790 }
1791
1792 while( ( TV.p[0] & 1 ) == 0 )
1793 {
1794 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1795
1796 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1797 {
1798 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1799 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1800 }
1801
1802 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1803 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1804 }
1805
1806 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1807 {
1808 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1809 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1810 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1811 }
1812 else
1813 {
1814 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1815 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1816 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1817 }
1818 }
1819 while( mpi_cmp_int( &TU, 0 ) != 0 );
1820
1821 while( mpi_cmp_int( &V1, 0 ) < 0 )
1822 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1823
1824 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1825 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1826
1827 MPI_CHK( mpi_copy( X, &V1 ) );
1828
1829cleanup:
1830
Paul Bakker6c591fa2011-05-05 11:49:20 +00001831 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1832 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1833 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001834
1835 return( ret );
1836}
1837
Paul Bakkerd9374b02012-11-02 11:02:58 +00001838#if defined(POLARSSL_GENPRIME)
1839
Paul Bakker5121ce52009-01-03 21:22:43 +00001840static const int small_prime[] =
1841{
1842 3, 5, 7, 11, 13, 17, 19, 23,
1843 29, 31, 37, 41, 43, 47, 53, 59,
1844 61, 67, 71, 73, 79, 83, 89, 97,
1845 101, 103, 107, 109, 113, 127, 131, 137,
1846 139, 149, 151, 157, 163, 167, 173, 179,
1847 181, 191, 193, 197, 199, 211, 223, 227,
1848 229, 233, 239, 241, 251, 257, 263, 269,
1849 271, 277, 281, 283, 293, 307, 311, 313,
1850 317, 331, 337, 347, 349, 353, 359, 367,
1851 373, 379, 383, 389, 397, 401, 409, 419,
1852 421, 431, 433, 439, 443, 449, 457, 461,
1853 463, 467, 479, 487, 491, 499, 503, 509,
1854 521, 523, 541, 547, 557, 563, 569, 571,
1855 577, 587, 593, 599, 601, 607, 613, 617,
1856 619, 631, 641, 643, 647, 653, 659, 661,
1857 673, 677, 683, 691, 701, 709, 719, 727,
1858 733, 739, 743, 751, 757, 761, 769, 773,
1859 787, 797, 809, 811, 821, 823, 827, 829,
1860 839, 853, 857, 859, 863, 877, 881, 883,
1861 887, 907, 911, 919, 929, 937, 941, 947,
1862 953, 967, 971, 977, 983, 991, 997, -103
1863};
1864
1865/*
1866 * Miller-Rabin primality test (HAC 4.24)
1867 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001868int mpi_is_prime( mpi *X,
1869 int (*f_rng)(void *, unsigned char *, size_t),
1870 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001871{
Paul Bakker23986e52011-04-24 08:57:21 +00001872 int ret, xs;
1873 size_t i, j, n, s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001874 mpi W, R, T, A, RR;
Paul Bakker5121ce52009-01-03 21:22:43 +00001875
Paul Bakker48eab262009-06-25 21:25:49 +00001876 if( mpi_cmp_int( X, 0 ) == 0 ||
1877 mpi_cmp_int( X, 1 ) == 0 )
1878 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1879
1880 if( mpi_cmp_int( X, 2 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001881 return( 0 );
1882
Paul Bakker6c591fa2011-05-05 11:49:20 +00001883 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
1884 mpi_init( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001885
1886 xs = X->s; X->s = 1;
1887
1888 /*
1889 * test trivial factors first
1890 */
1891 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001892 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001893
1894 for( i = 0; small_prime[i] > 0; i++ )
1895 {
Paul Bakkera755ca12011-04-24 09:11:17 +00001896 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001897
1898 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
1899 return( 0 );
1900
1901 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1902
1903 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001904 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001905 }
1906
1907 /*
1908 * W = |X| - 1
1909 * R = W >> lsb( W )
1910 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001911 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001912 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001913 MPI_CHK( mpi_copy( &R, &W ) );
1914 MPI_CHK( mpi_shift_r( &R, s ) );
1915
1916 i = mpi_msb( X );
1917 /*
1918 * HAC, table 4.4
1919 */
1920 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1921 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1922 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1923
1924 for( i = 0; i < n; i++ )
1925 {
1926 /*
1927 * pick a random A, 1 < A < |X| - 1
1928 */
Paul Bakker901c6562012-04-20 13:25:38 +00001929 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001930
Paul Bakkerb94081b2011-01-05 15:53:06 +00001931 if( mpi_cmp_mpi( &A, &W ) >= 0 )
1932 {
1933 j = mpi_msb( &A ) - mpi_msb( &W );
1934 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1935 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001936 A.p[0] |= 3;
1937
1938 /*
1939 * A = A^R mod |X|
1940 */
1941 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1942
1943 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1944 mpi_cmp_int( &A, 1 ) == 0 )
1945 continue;
1946
1947 j = 1;
1948 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1949 {
1950 /*
1951 * A = A * A mod |X|
1952 */
1953 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1954 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1955
1956 if( mpi_cmp_int( &A, 1 ) == 0 )
1957 break;
1958
1959 j++;
1960 }
1961
1962 /*
1963 * not prime if A != |X| - 1 or A == 1
1964 */
1965 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1966 mpi_cmp_int( &A, 1 ) == 0 )
1967 {
Paul Bakker40e46942009-01-03 21:51:57 +00001968 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001969 break;
1970 }
1971 }
1972
1973cleanup:
1974
1975 X->s = xs;
1976
Paul Bakker6c591fa2011-05-05 11:49:20 +00001977 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
1978 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001979
1980 return( ret );
1981}
1982
1983/*
1984 * Prime number generation
1985 */
Paul Bakker23986e52011-04-24 08:57:21 +00001986int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001987 int (*f_rng)(void *, unsigned char *, size_t),
1988 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001989{
Paul Bakker23986e52011-04-24 08:57:21 +00001990 int ret;
1991 size_t k, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001992 mpi Y;
1993
Paul Bakkerfe3256e2011-11-25 12:11:43 +00001994 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00001995 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001996
Paul Bakker6c591fa2011-05-05 11:49:20 +00001997 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001998
1999 n = BITS_TO_LIMBS( nbits );
2000
Paul Bakker901c6562012-04-20 13:25:38 +00002001 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002002
2003 k = mpi_msb( X );
2004 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
2005 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
2006
2007 X->p[0] |= 3;
2008
2009 if( dh_flag == 0 )
2010 {
2011 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
2012 {
Paul Bakker40e46942009-01-03 21:51:57 +00002013 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002014 goto cleanup;
2015
2016 MPI_CHK( mpi_add_int( X, X, 2 ) );
2017 }
2018 }
2019 else
2020 {
2021 MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
2022 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2023
2024 while( 1 )
2025 {
2026 if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
2027 {
2028 if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
2029 break;
2030
Paul Bakker40e46942009-01-03 21:51:57 +00002031 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002032 goto cleanup;
2033 }
2034
Paul Bakker40e46942009-01-03 21:51:57 +00002035 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002036 goto cleanup;
2037
2038 MPI_CHK( mpi_add_int( &Y, X, 1 ) );
2039 MPI_CHK( mpi_add_int( X, X, 2 ) );
2040 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2041 }
2042 }
2043
2044cleanup:
2045
Paul Bakker6c591fa2011-05-05 11:49:20 +00002046 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002047
2048 return( ret );
2049}
2050
Manuel Pégourié-Gonnarddf0142b2013-08-22 18:29:07 +02002051#endif /* POLARSSL_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002052
Paul Bakker40e46942009-01-03 21:51:57 +00002053#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002054
Paul Bakker23986e52011-04-24 08:57:21 +00002055#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002056
2057static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2058{
2059 { 693, 609, 21 },
2060 { 1764, 868, 28 },
2061 { 768454923, 542167814, 1 }
2062};
2063
Paul Bakker5121ce52009-01-03 21:22:43 +00002064/*
2065 * Checkup routine
2066 */
2067int mpi_self_test( int verbose )
2068{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002069 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002070 mpi A, E, N, X, Y, U, V;
2071
Paul Bakker6c591fa2011-05-05 11:49:20 +00002072 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2073 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002074
2075 MPI_CHK( mpi_read_string( &A, 16,
2076 "EFE021C2645FD1DC586E69184AF4A31E" \
2077 "D5F53E93B5F123FA41680867BA110131" \
2078 "944FE7952E2517337780CB0DB80E61AA" \
2079 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2080
2081 MPI_CHK( mpi_read_string( &E, 16,
2082 "B2E7EFD37075B9F03FF989C7C5051C20" \
2083 "34D2A323810251127E7BF8625A4F49A5" \
2084 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2085 "5B5C25763222FEFCCFC38B832366C29E" ) );
2086
2087 MPI_CHK( mpi_read_string( &N, 16,
2088 "0066A198186C18C10B2F5ED9B522752A" \
2089 "9830B69916E535C8F047518A889A43A5" \
2090 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2091
2092 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2093
2094 MPI_CHK( mpi_read_string( &U, 16,
2095 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2096 "9E857EA95A03512E2BAE7391688D264A" \
2097 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2098 "8001B72E848A38CAE1C65F78E56ABDEF" \
2099 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2100 "ECF677152EF804370C1A305CAF3B5BF1" \
2101 "30879B56C61DE584A0F53A2447A51E" ) );
2102
2103 if( verbose != 0 )
2104 printf( " MPI test #1 (mul_mpi): " );
2105
2106 if( mpi_cmp_mpi( &X, &U ) != 0 )
2107 {
2108 if( verbose != 0 )
2109 printf( "failed\n" );
2110
2111 return( 1 );
2112 }
2113
2114 if( verbose != 0 )
2115 printf( "passed\n" );
2116
2117 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2118
2119 MPI_CHK( mpi_read_string( &U, 16,
2120 "256567336059E52CAE22925474705F39A94" ) );
2121
2122 MPI_CHK( mpi_read_string( &V, 16,
2123 "6613F26162223DF488E9CD48CC132C7A" \
2124 "0AC93C701B001B092E4E5B9F73BCD27B" \
2125 "9EE50D0657C77F374E903CDFA4C642" ) );
2126
2127 if( verbose != 0 )
2128 printf( " MPI test #2 (div_mpi): " );
2129
2130 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2131 mpi_cmp_mpi( &Y, &V ) != 0 )
2132 {
2133 if( verbose != 0 )
2134 printf( "failed\n" );
2135
2136 return( 1 );
2137 }
2138
2139 if( verbose != 0 )
2140 printf( "passed\n" );
2141
2142 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2143
2144 MPI_CHK( mpi_read_string( &U, 16,
2145 "36E139AEA55215609D2816998ED020BB" \
2146 "BD96C37890F65171D948E9BC7CBAA4D9" \
2147 "325D24D6A3C12710F10A09FA08AB87" ) );
2148
2149 if( verbose != 0 )
2150 printf( " MPI test #3 (exp_mod): " );
2151
2152 if( mpi_cmp_mpi( &X, &U ) != 0 )
2153 {
2154 if( verbose != 0 )
2155 printf( "failed\n" );
2156
2157 return( 1 );
2158 }
2159
2160 if( verbose != 0 )
2161 printf( "passed\n" );
2162
2163 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2164
2165 MPI_CHK( mpi_read_string( &U, 16,
2166 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2167 "C3DBA76456363A10869622EAC2DD84EC" \
2168 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2169
2170 if( verbose != 0 )
2171 printf( " MPI test #4 (inv_mod): " );
2172
2173 if( mpi_cmp_mpi( &X, &U ) != 0 )
2174 {
2175 if( verbose != 0 )
2176 printf( "failed\n" );
2177
2178 return( 1 );
2179 }
2180
2181 if( verbose != 0 )
2182 printf( "passed\n" );
2183
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002184 if( verbose != 0 )
2185 printf( " MPI test #5 (simple gcd): " );
2186
2187 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2188 {
2189 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002190 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002191
Paul Bakker23986e52011-04-24 08:57:21 +00002192 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002193
Paul Bakker23986e52011-04-24 08:57:21 +00002194 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2195 {
2196 if( verbose != 0 )
2197 printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002198
Paul Bakker23986e52011-04-24 08:57:21 +00002199 return( 1 );
2200 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002201 }
2202
2203 if( verbose != 0 )
2204 printf( "passed\n" );
2205
Paul Bakker5121ce52009-01-03 21:22:43 +00002206cleanup:
2207
2208 if( ret != 0 && verbose != 0 )
2209 printf( "Unexpected error, return code = %08X\n", ret );
2210
Paul Bakker6c591fa2011-05-05 11:49:20 +00002211 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2212 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002213
2214 if( verbose != 0 )
2215 printf( "\n" );
2216
2217 return( ret );
2218}
2219
2220#endif
2221
2222#endif