blob: acaba6a7e16d33c5f9268568f1b4b09f5aeb7f5e [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 Bakker5121ce52009-01-03 21:22:43 +000040#include <stdlib.h>
Paul Bakker5121ce52009-01-03 21:22:43 +000041
Paul Bakkerf9688572011-05-05 10:00:45 +000042#define ciL (sizeof(t_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000043#define biL (ciL << 3) /* bits in limb */
44#define biH (ciL << 2) /* half limb size */
45
46/*
47 * Convert between bits/chars and number of limbs
48 */
49#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL)
50#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
51
52/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000053 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000054 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000055void mpi_init( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000056{
Paul Bakker6c591fa2011-05-05 11:49:20 +000057 if( X == NULL )
58 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000059
Paul Bakker6c591fa2011-05-05 11:49:20 +000060 X->s = 1;
61 X->n = 0;
62 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000063}
64
65/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000066 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000067 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000068void mpi_free( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000069{
Paul Bakker6c591fa2011-05-05 11:49:20 +000070 if( X == NULL )
71 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000072
Paul Bakker6c591fa2011-05-05 11:49:20 +000073 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +000074 {
Paul Bakker6c591fa2011-05-05 11:49:20 +000075 memset( X->p, 0, X->n * ciL );
76 free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +000077 }
78
Paul Bakker6c591fa2011-05-05 11:49:20 +000079 X->s = 1;
80 X->n = 0;
81 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000082}
83
84/*
85 * Enlarge to the specified number of limbs
86 */
Paul Bakker23986e52011-04-24 08:57:21 +000087int mpi_grow( mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +000088{
Paul Bakkera755ca12011-04-24 09:11:17 +000089 t_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +000090
Paul Bakkerf9688572011-05-05 10:00:45 +000091 if( nblimbs > POLARSSL_MPI_MAX_LIMBS )
Paul Bakker732e1a82011-12-11 16:35:09 +000092 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +000093
Paul Bakker5121ce52009-01-03 21:22:43 +000094 if( X->n < nblimbs )
95 {
Paul Bakkera755ca12011-04-24 09:11:17 +000096 if( ( p = (t_uint *) malloc( nblimbs * ciL ) ) == NULL )
Paul Bakker732e1a82011-12-11 16:35:09 +000097 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +000098
99 memset( p, 0, nblimbs * ciL );
100
101 if( X->p != NULL )
102 {
103 memcpy( p, X->p, X->n * ciL );
104 memset( X->p, 0, X->n * ciL );
105 free( X->p );
106 }
107
108 X->n = nblimbs;
109 X->p = p;
110 }
111
112 return( 0 );
113}
114
115/*
116 * Copy the contents of Y into X
117 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000118int mpi_copy( mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000119{
Paul Bakker23986e52011-04-24 08:57:21 +0000120 int ret;
121 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000122
123 if( X == Y )
124 return( 0 );
125
126 for( i = Y->n - 1; i > 0; i-- )
127 if( Y->p[i] != 0 )
128 break;
129 i++;
130
131 X->s = Y->s;
132
133 MPI_CHK( mpi_grow( X, i ) );
134
135 memset( X->p, 0, X->n * ciL );
136 memcpy( X->p, Y->p, i * ciL );
137
138cleanup:
139
140 return( ret );
141}
142
143/*
144 * Swap the contents of X and Y
145 */
146void mpi_swap( mpi *X, mpi *Y )
147{
148 mpi T;
149
150 memcpy( &T, X, sizeof( mpi ) );
151 memcpy( X, Y, sizeof( mpi ) );
152 memcpy( Y, &T, sizeof( mpi ) );
153}
154
155/*
156 * Set value from integer
157 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000158int mpi_lset( mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000159{
160 int ret;
161
162 MPI_CHK( mpi_grow( X, 1 ) );
163 memset( X->p, 0, X->n * ciL );
164
165 X->p[0] = ( z < 0 ) ? -z : z;
166 X->s = ( z < 0 ) ? -1 : 1;
167
168cleanup:
169
170 return( ret );
171}
172
173/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000174 * Get a specific bit
175 */
176int mpi_get_bit( mpi *X, size_t pos )
177{
178 if( X->n * biL <= pos )
179 return( 0 );
180
181 return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
182}
183
184/*
185 * Set a bit to a specific value of 0 or 1
186 */
187int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
188{
189 int ret = 0;
190 size_t off = pos / biL;
191 size_t idx = pos % biL;
192
193 if( val != 0 && val != 1 )
194 return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
195
196 if( X->n * biL <= pos )
197 {
198 if( val == 0 )
199 return ( 0 );
200
201 MPI_CHK( mpi_grow( X, off + 1 ) );
202 }
203
204 X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
205
206cleanup:
207
208 return( ret );
209}
210
211/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000212 * Return the number of least significant bits
213 */
Paul Bakker23986e52011-04-24 08:57:21 +0000214size_t mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000215{
Paul Bakker23986e52011-04-24 08:57:21 +0000216 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000217
218 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000219 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000220 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
221 return( count );
222
223 return( 0 );
224}
225
226/*
227 * Return the number of most significant bits
228 */
Paul Bakker23986e52011-04-24 08:57:21 +0000229size_t mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000230{
Paul Bakker23986e52011-04-24 08:57:21 +0000231 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000232
233 for( i = X->n - 1; i > 0; i-- )
234 if( X->p[i] != 0 )
235 break;
236
Paul Bakker23986e52011-04-24 08:57:21 +0000237 for( j = biL; j > 0; j-- )
238 if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000239 break;
240
Paul Bakker23986e52011-04-24 08:57:21 +0000241 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000242}
243
244/*
245 * Return the total size in bytes
246 */
Paul Bakker23986e52011-04-24 08:57:21 +0000247size_t mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000248{
249 return( ( mpi_msb( X ) + 7 ) >> 3 );
250}
251
252/*
253 * Convert an ASCII character to digit value
254 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000255static int mpi_get_digit( t_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000256{
257 *d = 255;
258
259 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
260 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
261 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
262
Paul Bakkera755ca12011-04-24 09:11:17 +0000263 if( *d >= (t_uint) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000264 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000265
266 return( 0 );
267}
268
269/*
270 * Import from an ASCII string
271 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000272int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000273{
Paul Bakker23986e52011-04-24 08:57:21 +0000274 int ret;
275 size_t i, j, slen, n;
Paul Bakkera755ca12011-04-24 09:11:17 +0000276 t_uint d;
Paul Bakker5121ce52009-01-03 21:22:43 +0000277 mpi T;
278
279 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000280 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000281
Paul Bakker6c591fa2011-05-05 11:49:20 +0000282 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000283
Paul Bakkerff60ee62010-03-16 21:09:09 +0000284 slen = strlen( s );
285
Paul Bakker5121ce52009-01-03 21:22:43 +0000286 if( radix == 16 )
287 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000288 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000289
290 MPI_CHK( mpi_grow( X, n ) );
291 MPI_CHK( mpi_lset( X, 0 ) );
292
Paul Bakker23986e52011-04-24 08:57:21 +0000293 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000294 {
Paul Bakker23986e52011-04-24 08:57:21 +0000295 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000296 {
297 X->s = -1;
298 break;
299 }
300
Paul Bakker23986e52011-04-24 08:57:21 +0000301 MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000302 X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
303 }
304 }
305 else
306 {
307 MPI_CHK( mpi_lset( X, 0 ) );
308
Paul Bakkerff60ee62010-03-16 21:09:09 +0000309 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000310 {
311 if( i == 0 && s[i] == '-' )
312 {
313 X->s = -1;
314 continue;
315 }
316
317 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
318 MPI_CHK( mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000319
320 if( X->s == 1 )
321 {
322 MPI_CHK( mpi_add_int( X, &T, d ) );
323 }
324 else
325 {
326 MPI_CHK( mpi_sub_int( X, &T, d ) );
327 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000328 }
329 }
330
331cleanup:
332
Paul Bakker6c591fa2011-05-05 11:49:20 +0000333 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000334
335 return( ret );
336}
337
338/*
339 * Helper to write the digits high-order first
340 */
341static int mpi_write_hlp( mpi *X, int radix, char **p )
342{
343 int ret;
Paul Bakkera755ca12011-04-24 09:11:17 +0000344 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000345
346 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000347 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000348
349 MPI_CHK( mpi_mod_int( &r, X, radix ) );
350 MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
351
352 if( mpi_cmp_int( X, 0 ) != 0 )
353 MPI_CHK( mpi_write_hlp( X, radix, p ) );
354
355 if( r < 10 )
356 *(*p)++ = (char)( r + 0x30 );
357 else
358 *(*p)++ = (char)( r + 0x37 );
359
360cleanup:
361
362 return( ret );
363}
364
365/*
366 * Export into an ASCII string
367 */
Paul Bakker23986e52011-04-24 08:57:21 +0000368int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000369{
Paul Bakker23986e52011-04-24 08:57:21 +0000370 int ret = 0;
371 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000372 char *p;
373 mpi T;
374
375 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000376 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000377
378 n = mpi_msb( X );
379 if( radix >= 4 ) n >>= 1;
380 if( radix >= 16 ) n >>= 1;
381 n += 3;
382
383 if( *slen < n )
384 {
385 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000386 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 }
388
389 p = s;
Paul Bakker6c591fa2011-05-05 11:49:20 +0000390 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000391
392 if( X->s == -1 )
393 *p++ = '-';
394
395 if( radix == 16 )
396 {
Paul Bakker23986e52011-04-24 08:57:21 +0000397 int c;
398 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000399
Paul Bakker23986e52011-04-24 08:57:21 +0000400 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000401 {
Paul Bakker23986e52011-04-24 08:57:21 +0000402 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000403 {
Paul Bakker23986e52011-04-24 08:57:21 +0000404 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000405
Paul Bakker23986e52011-04-24 08:57:21 +0000406 if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000407 continue;
408
409 p += sprintf( p, "%02X", c );
410 k = 1;
411 }
412 }
413 }
414 else
415 {
416 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000417
418 if( T.s == -1 )
419 T.s = 1;
420
Paul Bakker5121ce52009-01-03 21:22:43 +0000421 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
422 }
423
424 *p++ = '\0';
425 *slen = p - s;
426
427cleanup:
428
Paul Bakker6c591fa2011-05-05 11:49:20 +0000429 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000430
431 return( ret );
432}
433
Paul Bakker335db3f2011-04-25 15:28:35 +0000434#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000435/*
436 * Read X from an opened file
437 */
438int mpi_read_file( mpi *X, int radix, FILE *fin )
439{
Paul Bakkera755ca12011-04-24 09:11:17 +0000440 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000441 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000442 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000443 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000444 * Buffer should have space for (short) label and decimal formatted MPI,
445 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000446 */
Paul Bakkercb37aa52011-11-30 16:00:20 +0000447 char s[ POLARSSL_MPI_READ_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000448
449 memset( s, 0, sizeof( s ) );
450 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000451 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000452
453 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000454 if( slen == sizeof( s ) - 2 )
455 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
456
Paul Bakker5121ce52009-01-03 21:22:43 +0000457 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
458 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
459
460 p = s + slen;
461 while( --p >= s )
462 if( mpi_get_digit( &d, radix, *p ) != 0 )
463 break;
464
465 return( mpi_read_string( X, radix, p + 1 ) );
466}
467
468/*
469 * Write X into an opened file (or stdout if fout == NULL)
470 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000471int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000472{
Paul Bakker23986e52011-04-24 08:57:21 +0000473 int ret;
474 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000475 /*
476 * Buffer should have space for minus sign, hexified MPI and '\0'
477 */
478 char s[ 2 * POLARSSL_MPI_MAX_SIZE + 2 ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000479
480 n = sizeof( s );
481 memset( s, 0, n );
482 n -= 2;
483
Paul Bakker23986e52011-04-24 08:57:21 +0000484 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000485
486 if( p == NULL ) p = "";
487
488 plen = strlen( p );
489 slen = strlen( s );
490 s[slen++] = '\r';
491 s[slen++] = '\n';
492
493 if( fout != NULL )
494 {
495 if( fwrite( p, 1, plen, fout ) != plen ||
496 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000497 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000498 }
499 else
500 printf( "%s%s", p, s );
501
502cleanup:
503
504 return( ret );
505}
Paul Bakker335db3f2011-04-25 15:28:35 +0000506#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000507
508/*
509 * Import X from unsigned binary data, big endian
510 */
Paul Bakker23986e52011-04-24 08:57:21 +0000511int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000512{
Paul Bakker23986e52011-04-24 08:57:21 +0000513 int ret;
514 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000515
516 for( n = 0; n < buflen; n++ )
517 if( buf[n] != 0 )
518 break;
519
520 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
521 MPI_CHK( mpi_lset( X, 0 ) );
522
Paul Bakker23986e52011-04-24 08:57:21 +0000523 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000524 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000525
526cleanup:
527
528 return( ret );
529}
530
531/*
532 * Export X into unsigned binary data, big endian
533 */
Paul Bakker23986e52011-04-24 08:57:21 +0000534int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000535{
Paul Bakker23986e52011-04-24 08:57:21 +0000536 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000537
538 n = mpi_size( X );
539
540 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000541 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000542
543 memset( buf, 0, buflen );
544
545 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
546 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
547
548 return( 0 );
549}
550
551/*
552 * Left-shift: X <<= count
553 */
Paul Bakker23986e52011-04-24 08:57:21 +0000554int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000555{
Paul Bakker23986e52011-04-24 08:57:21 +0000556 int ret;
557 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000558 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000559
560 v0 = count / (biL );
561 t1 = count & (biL - 1);
562
563 i = mpi_msb( X ) + count;
564
Paul Bakkerf9688572011-05-05 10:00:45 +0000565 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000566 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
567
568 ret = 0;
569
570 /*
571 * shift by count / limb_size
572 */
573 if( v0 > 0 )
574 {
Paul Bakker23986e52011-04-24 08:57:21 +0000575 for( i = X->n; i > v0; i-- )
576 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000577
Paul Bakker23986e52011-04-24 08:57:21 +0000578 for( ; i > 0; i-- )
579 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000580 }
581
582 /*
583 * shift by count % limb_size
584 */
585 if( t1 > 0 )
586 {
587 for( i = v0; i < X->n; i++ )
588 {
589 r1 = X->p[i] >> (biL - t1);
590 X->p[i] <<= t1;
591 X->p[i] |= r0;
592 r0 = r1;
593 }
594 }
595
596cleanup:
597
598 return( ret );
599}
600
601/*
602 * Right-shift: X >>= count
603 */
Paul Bakker23986e52011-04-24 08:57:21 +0000604int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000605{
Paul Bakker23986e52011-04-24 08:57:21 +0000606 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000607 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000608
609 v0 = count / biL;
610 v1 = count & (biL - 1);
611
Manuel Pégourié-Gonnardf173e0a2012-11-17 12:42:51 +0100612 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
613 return mpi_lset( X, 0 );
614
Paul Bakker5121ce52009-01-03 21:22:43 +0000615 /*
616 * shift by count / limb_size
617 */
618 if( v0 > 0 )
619 {
620 for( i = 0; i < X->n - v0; i++ )
621 X->p[i] = X->p[i + v0];
622
623 for( ; i < X->n; i++ )
624 X->p[i] = 0;
625 }
626
627 /*
628 * shift by count % limb_size
629 */
630 if( v1 > 0 )
631 {
Paul Bakker23986e52011-04-24 08:57:21 +0000632 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000633 {
Paul Bakker23986e52011-04-24 08:57:21 +0000634 r1 = X->p[i - 1] << (biL - v1);
635 X->p[i - 1] >>= v1;
636 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000637 r0 = r1;
638 }
639 }
640
641 return( 0 );
642}
643
644/*
645 * Compare unsigned values
646 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000647int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000648{
Paul Bakker23986e52011-04-24 08:57:21 +0000649 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000650
Paul Bakker23986e52011-04-24 08:57:21 +0000651 for( i = X->n; i > 0; i-- )
652 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000653 break;
654
Paul Bakker23986e52011-04-24 08:57:21 +0000655 for( j = Y->n; j > 0; j-- )
656 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000657 break;
658
Paul Bakker23986e52011-04-24 08:57:21 +0000659 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000660 return( 0 );
661
662 if( i > j ) return( 1 );
663 if( j > i ) return( -1 );
664
Paul Bakker23986e52011-04-24 08:57:21 +0000665 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000666 {
Paul Bakker23986e52011-04-24 08:57:21 +0000667 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
668 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000669 }
670
671 return( 0 );
672}
673
674/*
675 * Compare signed values
676 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000677int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000678{
Paul Bakker23986e52011-04-24 08:57:21 +0000679 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000680
Paul Bakker23986e52011-04-24 08:57:21 +0000681 for( i = X->n; i > 0; i-- )
682 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000683 break;
684
Paul Bakker23986e52011-04-24 08:57:21 +0000685 for( j = Y->n; j > 0; j-- )
686 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000687 break;
688
Paul Bakker23986e52011-04-24 08:57:21 +0000689 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000690 return( 0 );
691
692 if( i > j ) return( X->s );
Paul Bakker32356ac2012-04-20 13:34:52 +0000693 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000694
695 if( X->s > 0 && Y->s < 0 ) return( 1 );
696 if( Y->s > 0 && X->s < 0 ) return( -1 );
697
Paul Bakker23986e52011-04-24 08:57:21 +0000698 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000699 {
Paul Bakker23986e52011-04-24 08:57:21 +0000700 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
701 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000702 }
703
704 return( 0 );
705}
706
707/*
708 * Compare signed values
709 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000710int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000711{
712 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000713 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000714
715 *p = ( z < 0 ) ? -z : z;
716 Y.s = ( z < 0 ) ? -1 : 1;
717 Y.n = 1;
718 Y.p = p;
719
720 return( mpi_cmp_mpi( X, &Y ) );
721}
722
723/*
724 * Unsigned addition: X = |A| + |B| (HAC 14.7)
725 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000726int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000727{
Paul Bakker23986e52011-04-24 08:57:21 +0000728 int ret;
729 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000730 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000731
732 if( X == B )
733 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000734 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000735 }
736
737 if( X != A )
738 MPI_CHK( mpi_copy( X, A ) );
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000739
740 /*
741 * X should always be positive as a result of unsigned additions.
742 */
743 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000744
Paul Bakker23986e52011-04-24 08:57:21 +0000745 for( j = B->n; j > 0; j-- )
746 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000747 break;
748
Paul Bakker23986e52011-04-24 08:57:21 +0000749 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000750
751 o = B->p; p = X->p; c = 0;
752
Paul Bakker23986e52011-04-24 08:57:21 +0000753 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000754 {
755 *p += c; c = ( *p < c );
756 *p += *o; c += ( *p < *o );
757 }
758
759 while( c != 0 )
760 {
761 if( i >= X->n )
762 {
763 MPI_CHK( mpi_grow( X, i + 1 ) );
764 p = X->p + i;
765 }
766
Paul Bakkerebee0762012-09-16 21:34:26 +0000767 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000768 }
769
770cleanup:
771
772 return( ret );
773}
774
775/*
776 * Helper for mpi substraction
777 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000778static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000779{
Paul Bakker23986e52011-04-24 08:57:21 +0000780 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000781 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000782
783 for( i = c = 0; i < n; i++, s++, d++ )
784 {
785 z = ( *d < c ); *d -= c;
786 c = ( *d < *s ) + z; *d -= *s;
787 }
788
789 while( c != 0 )
790 {
791 z = ( *d < c ); *d -= c;
792 c = z; i++; d++;
793 }
794}
795
796/*
797 * Unsigned substraction: X = |A| - |B| (HAC 14.9)
798 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000799int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000800{
801 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000802 int ret;
803 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000804
805 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000806 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000807
Paul Bakker6c591fa2011-05-05 11:49:20 +0000808 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000809
810 if( X == B )
811 {
812 MPI_CHK( mpi_copy( &TB, B ) );
813 B = &TB;
814 }
815
816 if( X != A )
817 MPI_CHK( mpi_copy( X, A ) );
818
Paul Bakker1ef7a532009-06-20 10:50:55 +0000819 /*
820 * X should always be positive as a result of unsigned substractions.
821 */
822 X->s = 1;
823
Paul Bakker5121ce52009-01-03 21:22:43 +0000824 ret = 0;
825
Paul Bakker23986e52011-04-24 08:57:21 +0000826 for( n = B->n; n > 0; n-- )
827 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000828 break;
829
Paul Bakker23986e52011-04-24 08:57:21 +0000830 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000831
832cleanup:
833
Paul Bakker6c591fa2011-05-05 11:49:20 +0000834 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000835
836 return( ret );
837}
838
839/*
840 * Signed addition: X = A + B
841 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000842int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000843{
844 int ret, s = A->s;
845
846 if( A->s * B->s < 0 )
847 {
848 if( mpi_cmp_abs( A, B ) >= 0 )
849 {
850 MPI_CHK( mpi_sub_abs( X, A, B ) );
851 X->s = s;
852 }
853 else
854 {
855 MPI_CHK( mpi_sub_abs( X, B, A ) );
856 X->s = -s;
857 }
858 }
859 else
860 {
861 MPI_CHK( mpi_add_abs( X, A, B ) );
862 X->s = s;
863 }
864
865cleanup:
866
867 return( ret );
868}
869
870/*
871 * Signed substraction: X = A - B
872 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000873int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000874{
875 int ret, s = A->s;
876
877 if( A->s * B->s > 0 )
878 {
879 if( mpi_cmp_abs( A, B ) >= 0 )
880 {
881 MPI_CHK( mpi_sub_abs( X, A, B ) );
882 X->s = s;
883 }
884 else
885 {
886 MPI_CHK( mpi_sub_abs( X, B, A ) );
887 X->s = -s;
888 }
889 }
890 else
891 {
892 MPI_CHK( mpi_add_abs( X, A, B ) );
893 X->s = s;
894 }
895
896cleanup:
897
898 return( ret );
899}
900
901/*
902 * Signed addition: X = A + b
903 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000904int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000905{
906 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000907 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000908
909 p[0] = ( b < 0 ) ? -b : b;
910 _B.s = ( b < 0 ) ? -1 : 1;
911 _B.n = 1;
912 _B.p = p;
913
914 return( mpi_add_mpi( X, A, &_B ) );
915}
916
917/*
918 * Signed substraction: X = A - b
919 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000920int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000921{
922 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000923 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000924
925 p[0] = ( b < 0 ) ? -b : b;
926 _B.s = ( b < 0 ) ? -1 : 1;
927 _B.n = 1;
928 _B.p = p;
929
930 return( mpi_sub_mpi( X, A, &_B ) );
931}
932
933/*
934 * Helper for mpi multiplication
935 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000936static void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000937{
Paul Bakkera755ca12011-04-24 09:11:17 +0000938 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000939
940#if defined(MULADDC_HUIT)
941 for( ; i >= 8; i -= 8 )
942 {
943 MULADDC_INIT
944 MULADDC_HUIT
945 MULADDC_STOP
946 }
947
948 for( ; i > 0; i-- )
949 {
950 MULADDC_INIT
951 MULADDC_CORE
952 MULADDC_STOP
953 }
954#else
955 for( ; i >= 16; i -= 16 )
956 {
957 MULADDC_INIT
958 MULADDC_CORE MULADDC_CORE
959 MULADDC_CORE MULADDC_CORE
960 MULADDC_CORE MULADDC_CORE
961 MULADDC_CORE MULADDC_CORE
962
963 MULADDC_CORE MULADDC_CORE
964 MULADDC_CORE MULADDC_CORE
965 MULADDC_CORE MULADDC_CORE
966 MULADDC_CORE MULADDC_CORE
967 MULADDC_STOP
968 }
969
970 for( ; i >= 8; i -= 8 )
971 {
972 MULADDC_INIT
973 MULADDC_CORE MULADDC_CORE
974 MULADDC_CORE MULADDC_CORE
975
976 MULADDC_CORE MULADDC_CORE
977 MULADDC_CORE MULADDC_CORE
978 MULADDC_STOP
979 }
980
981 for( ; i > 0; i-- )
982 {
983 MULADDC_INIT
984 MULADDC_CORE
985 MULADDC_STOP
986 }
987#endif
988
989 t++;
990
991 do {
992 *d += c; c = ( *d < c ); d++;
993 }
994 while( c != 0 );
995}
996
997/*
998 * Baseline multiplication: X = A * B (HAC 14.12)
999 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001000int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001001{
Paul Bakker23986e52011-04-24 08:57:21 +00001002 int ret;
1003 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001004 mpi TA, TB;
1005
Paul Bakker6c591fa2011-05-05 11:49:20 +00001006 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001007
1008 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1009 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1010
Paul Bakker23986e52011-04-24 08:57:21 +00001011 for( i = A->n; i > 0; i-- )
1012 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001013 break;
1014
Paul Bakker23986e52011-04-24 08:57:21 +00001015 for( j = B->n; j > 0; j-- )
1016 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001017 break;
1018
Paul Bakker23986e52011-04-24 08:57:21 +00001019 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001020 MPI_CHK( mpi_lset( X, 0 ) );
1021
Paul Bakker23986e52011-04-24 08:57:21 +00001022 for( i++; j > 0; j-- )
1023 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001024
1025 X->s = A->s * B->s;
1026
1027cleanup:
1028
Paul Bakker6c591fa2011-05-05 11:49:20 +00001029 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001030
1031 return( ret );
1032}
1033
1034/*
1035 * Baseline multiplication: X = A * b
1036 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001037int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001038{
1039 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001040 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001041
1042 _B.s = 1;
1043 _B.n = 1;
1044 _B.p = p;
1045 p[0] = b;
1046
1047 return( mpi_mul_mpi( X, A, &_B ) );
1048}
1049
1050/*
1051 * Division by mpi: A = Q * B + R (HAC 14.20)
1052 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001053int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001054{
Paul Bakker23986e52011-04-24 08:57:21 +00001055 int ret;
1056 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001057 mpi X, Y, Z, T1, T2;
1058
1059 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001060 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001061
Paul Bakker6c591fa2011-05-05 11:49:20 +00001062 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1063 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001064
1065 if( mpi_cmp_abs( A, B ) < 0 )
1066 {
1067 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1068 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1069 return( 0 );
1070 }
1071
1072 MPI_CHK( mpi_copy( &X, A ) );
1073 MPI_CHK( mpi_copy( &Y, B ) );
1074 X.s = Y.s = 1;
1075
1076 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1077 MPI_CHK( mpi_lset( &Z, 0 ) );
1078 MPI_CHK( mpi_grow( &T1, 2 ) );
1079 MPI_CHK( mpi_grow( &T2, 3 ) );
1080
1081 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001082 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001083 {
1084 k = biL - 1 - k;
1085 MPI_CHK( mpi_shift_l( &X, k ) );
1086 MPI_CHK( mpi_shift_l( &Y, k ) );
1087 }
1088 else k = 0;
1089
1090 n = X.n - 1;
1091 t = Y.n - 1;
1092 mpi_shift_l( &Y, biL * (n - t) );
1093
1094 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1095 {
1096 Z.p[n - t]++;
1097 mpi_sub_mpi( &X, &X, &Y );
1098 }
1099 mpi_shift_r( &Y, biL * (n - t) );
1100
1101 for( i = n; i > t ; i-- )
1102 {
1103 if( X.p[i] >= Y.p[t] )
1104 Z.p[i - t - 1] = ~0;
1105 else
1106 {
Paul Bakker40e46942009-01-03 21:51:57 +00001107#if defined(POLARSSL_HAVE_LONGLONG)
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001108 t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001109
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001110 r = (t_udbl) X.p[i] << biL;
1111 r |= (t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001112 r /= Y.p[t];
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001113 if( r > ((t_udbl) 1 << biL) - 1)
1114 r = ((t_udbl) 1 << biL) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001115
Paul Bakkera755ca12011-04-24 09:11:17 +00001116 Z.p[i - t - 1] = (t_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001117#else
1118 /*
1119 * __udiv_qrnnd_c, from gmp/longlong.h
1120 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001121 t_uint q0, q1, r0, r1;
1122 t_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001123
1124 d = Y.p[t];
1125 d0 = ( d << biH ) >> biH;
1126 d1 = ( d >> biH );
1127
1128 q1 = X.p[i] / d1;
1129 r1 = X.p[i] - d1 * q1;
1130 r1 <<= biH;
1131 r1 |= ( X.p[i - 1] >> biH );
1132
1133 m = q1 * d0;
1134 if( r1 < m )
1135 {
1136 q1--, r1 += d;
1137 while( r1 >= d && r1 < m )
1138 q1--, r1 += d;
1139 }
1140 r1 -= m;
1141
1142 q0 = r1 / d1;
1143 r0 = r1 - d1 * q0;
1144 r0 <<= biH;
1145 r0 |= ( X.p[i - 1] << biH ) >> biH;
1146
1147 m = q0 * d0;
1148 if( r0 < m )
1149 {
1150 q0--, r0 += d;
1151 while( r0 >= d && r0 < m )
1152 q0--, r0 += d;
1153 }
1154 r0 -= m;
1155
1156 Z.p[i - t - 1] = ( q1 << biH ) | q0;
1157#endif
1158 }
1159
1160 Z.p[i - t - 1]++;
1161 do
1162 {
1163 Z.p[i - t - 1]--;
1164
1165 MPI_CHK( mpi_lset( &T1, 0 ) );
1166 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1167 T1.p[1] = Y.p[t];
1168 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1169
1170 MPI_CHK( mpi_lset( &T2, 0 ) );
1171 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1172 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1173 T2.p[2] = X.p[i];
1174 }
1175 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1176
1177 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1178 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1179 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1180
1181 if( mpi_cmp_int( &X, 0 ) < 0 )
1182 {
1183 MPI_CHK( mpi_copy( &T1, &Y ) );
1184 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1185 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1186 Z.p[i - t - 1]--;
1187 }
1188 }
1189
1190 if( Q != NULL )
1191 {
1192 mpi_copy( Q, &Z );
1193 Q->s = A->s * B->s;
1194 }
1195
1196 if( R != NULL )
1197 {
1198 mpi_shift_r( &X, k );
1199 mpi_copy( R, &X );
1200
1201 R->s = A->s;
1202 if( mpi_cmp_int( R, 0 ) == 0 )
1203 R->s = 1;
1204 }
1205
1206cleanup:
1207
Paul Bakker6c591fa2011-05-05 11:49:20 +00001208 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1209 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001210
1211 return( ret );
1212}
1213
1214/*
1215 * Division by int: A = Q * b + R
1216 *
1217 * Returns 0 if successful
1218 * 1 if memory allocation failed
Paul Bakker40e46942009-01-03 21:51:57 +00001219 * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
Paul Bakker5121ce52009-01-03 21:22:43 +00001220 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001221int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001222{
1223 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001224 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001225
1226 p[0] = ( b < 0 ) ? -b : b;
1227 _B.s = ( b < 0 ) ? -1 : 1;
1228 _B.n = 1;
1229 _B.p = p;
1230
1231 return( mpi_div_mpi( Q, R, A, &_B ) );
1232}
1233
1234/*
1235 * Modulo: R = A mod B
1236 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001237int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001238{
1239 int ret;
1240
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001241 if( mpi_cmp_int( B, 0 ) < 0 )
1242 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1243
Paul Bakker5121ce52009-01-03 21:22:43 +00001244 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1245
1246 while( mpi_cmp_int( R, 0 ) < 0 )
1247 MPI_CHK( mpi_add_mpi( R, R, B ) );
1248
1249 while( mpi_cmp_mpi( R, B ) >= 0 )
1250 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1251
1252cleanup:
1253
1254 return( ret );
1255}
1256
1257/*
1258 * Modulo: r = A mod b
1259 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001260int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001261{
Paul Bakker23986e52011-04-24 08:57:21 +00001262 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001263 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001264
1265 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001266 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001267
1268 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001269 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001270
1271 /*
1272 * handle trivial cases
1273 */
1274 if( b == 1 )
1275 {
1276 *r = 0;
1277 return( 0 );
1278 }
1279
1280 if( b == 2 )
1281 {
1282 *r = A->p[0] & 1;
1283 return( 0 );
1284 }
1285
1286 /*
1287 * general case
1288 */
Paul Bakker23986e52011-04-24 08:57:21 +00001289 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001290 {
Paul Bakker23986e52011-04-24 08:57:21 +00001291 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001292 y = ( y << biH ) | ( x >> biH );
1293 z = y / b;
1294 y -= z * b;
1295
1296 x <<= biH;
1297 y = ( y << biH ) | ( x >> biH );
1298 z = y / b;
1299 y -= z * b;
1300 }
1301
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001302 /*
1303 * If A is negative, then the current y represents a negative value.
1304 * Flipping it to the positive side.
1305 */
1306 if( A->s < 0 && y != 0 )
1307 y = b - y;
1308
Paul Bakker5121ce52009-01-03 21:22:43 +00001309 *r = y;
1310
1311 return( 0 );
1312}
1313
1314/*
1315 * Fast Montgomery initialization (thanks to Tom St Denis)
1316 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001317static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001318{
Paul Bakkera755ca12011-04-24 09:11:17 +00001319 t_uint x, m0 = N->p[0];
Paul Bakker5121ce52009-01-03 21:22:43 +00001320
1321 x = m0;
1322 x += ( ( m0 + 2 ) & 4 ) << 1;
1323 x *= ( 2 - ( m0 * x ) );
1324
1325 if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
1326 if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
1327 if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
1328
1329 *mm = ~x + 1;
1330}
1331
1332/*
1333 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1334 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001335static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001336{
Paul Bakker23986e52011-04-24 08:57:21 +00001337 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001338 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001339
1340 memset( T->p, 0, T->n * ciL );
1341
1342 d = T->p;
1343 n = N->n;
1344 m = ( B->n < n ) ? B->n : n;
1345
1346 for( i = 0; i < n; i++ )
1347 {
1348 /*
1349 * T = (T + u0*B + u1*N) / 2^biL
1350 */
1351 u0 = A->p[i];
1352 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1353
1354 mpi_mul_hlp( m, B->p, d, u0 );
1355 mpi_mul_hlp( n, N->p, d, u1 );
1356
1357 *d++ = u0; d[n + 1] = 0;
1358 }
1359
1360 memcpy( A->p, d, (n + 1) * ciL );
1361
1362 if( mpi_cmp_abs( A, N ) >= 0 )
1363 mpi_sub_hlp( n, N->p, A->p );
1364 else
1365 /* prevent timing attacks */
1366 mpi_sub_hlp( n, A->p, T->p );
1367}
1368
1369/*
1370 * Montgomery reduction: A = A * R^-1 mod N
1371 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001372static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001373{
Paul Bakkera755ca12011-04-24 09:11:17 +00001374 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001375 mpi U;
1376
1377 U.n = U.s = z;
1378 U.p = &z;
1379
1380 mpi_montmul( A, &U, N, mm, T );
1381}
1382
1383/*
1384 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1385 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001386int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001387{
Paul Bakker23986e52011-04-24 08:57:21 +00001388 int ret;
1389 size_t wbits, wsize, one = 1;
1390 size_t i, j, nblimbs;
1391 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001392 t_uint ei, mm, state;
Paul Bakkerd8ee8442012-05-16 08:02:29 +00001393 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1394 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001395
1396 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001397 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001398
Paul Bakkerd8ee8442012-05-16 08:02:29 +00001399 if( mpi_cmp_int( E, 0 ) < 0 )
1400 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1401
1402 /*
1403 * Compensate for negative A (and correct at the end)
1404 */
1405 neg = ( A->s == -1 );
1406
1407 mpi_init( &Apos );
1408 if( neg )
1409 {
1410 MPI_CHK( mpi_copy( &Apos, A ) );
1411 Apos.s = 1;
1412 A = &Apos;
1413 }
1414
Paul Bakker5121ce52009-01-03 21:22:43 +00001415 /*
1416 * Init temps and window size
1417 */
1418 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001419 mpi_init( &RR ); mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001420 memset( W, 0, sizeof( W ) );
1421
1422 i = mpi_msb( E );
1423
1424 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1425 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1426
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001427 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1428 wsize = POLARSSL_MPI_WINDOW_SIZE;
1429
Paul Bakker5121ce52009-01-03 21:22:43 +00001430 j = N->n + 1;
1431 MPI_CHK( mpi_grow( X, j ) );
1432 MPI_CHK( mpi_grow( &W[1], j ) );
1433 MPI_CHK( mpi_grow( &T, j * 2 ) );
1434
1435 /*
1436 * If 1st call, pre-compute R^2 mod N
1437 */
1438 if( _RR == NULL || _RR->p == NULL )
1439 {
1440 MPI_CHK( mpi_lset( &RR, 1 ) );
1441 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1442 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1443
1444 if( _RR != NULL )
1445 memcpy( _RR, &RR, sizeof( mpi ) );
1446 }
1447 else
1448 memcpy( &RR, _RR, sizeof( mpi ) );
1449
1450 /*
1451 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1452 */
1453 if( mpi_cmp_mpi( A, N ) >= 0 )
1454 mpi_mod_mpi( &W[1], A, N );
1455 else mpi_copy( &W[1], A );
1456
1457 mpi_montmul( &W[1], &RR, N, mm, &T );
1458
1459 /*
1460 * X = R^2 * R^-1 mod N = R mod N
1461 */
1462 MPI_CHK( mpi_copy( X, &RR ) );
1463 mpi_montred( X, N, mm, &T );
1464
1465 if( wsize > 1 )
1466 {
1467 /*
1468 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1469 */
Paul Bakker23986e52011-04-24 08:57:21 +00001470 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001471
1472 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1473 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1474
1475 for( i = 0; i < wsize - 1; i++ )
1476 mpi_montmul( &W[j], &W[j], N, mm, &T );
1477
1478 /*
1479 * W[i] = W[i - 1] * W[1]
1480 */
Paul Bakker23986e52011-04-24 08:57:21 +00001481 for( i = j + 1; i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001482 {
1483 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1484 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1485
1486 mpi_montmul( &W[i], &W[1], N, mm, &T );
1487 }
1488 }
1489
1490 nblimbs = E->n;
1491 bufsize = 0;
1492 nbits = 0;
1493 wbits = 0;
1494 state = 0;
1495
1496 while( 1 )
1497 {
1498 if( bufsize == 0 )
1499 {
1500 if( nblimbs-- == 0 )
1501 break;
1502
Paul Bakkera755ca12011-04-24 09:11:17 +00001503 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001504 }
1505
1506 bufsize--;
1507
1508 ei = (E->p[nblimbs] >> bufsize) & 1;
1509
1510 /*
1511 * skip leading 0s
1512 */
1513 if( ei == 0 && state == 0 )
1514 continue;
1515
1516 if( ei == 0 && state == 1 )
1517 {
1518 /*
1519 * out of window, square X
1520 */
1521 mpi_montmul( X, X, N, mm, &T );
1522 continue;
1523 }
1524
1525 /*
1526 * add ei to current window
1527 */
1528 state = 2;
1529
1530 nbits++;
1531 wbits |= (ei << (wsize - nbits));
1532
1533 if( nbits == wsize )
1534 {
1535 /*
1536 * X = X^wsize R^-1 mod N
1537 */
1538 for( i = 0; i < wsize; i++ )
1539 mpi_montmul( X, X, N, mm, &T );
1540
1541 /*
1542 * X = X * W[wbits] R^-1 mod N
1543 */
1544 mpi_montmul( X, &W[wbits], N, mm, &T );
1545
1546 state--;
1547 nbits = 0;
1548 wbits = 0;
1549 }
1550 }
1551
1552 /*
1553 * process the remaining bits
1554 */
1555 for( i = 0; i < nbits; i++ )
1556 {
1557 mpi_montmul( X, X, N, mm, &T );
1558
1559 wbits <<= 1;
1560
Paul Bakker23986e52011-04-24 08:57:21 +00001561 if( (wbits & (one << wsize)) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001562 mpi_montmul( X, &W[1], N, mm, &T );
1563 }
1564
1565 /*
1566 * X = A^E * R * R^-1 mod N = A^E mod N
1567 */
1568 mpi_montred( X, N, mm, &T );
1569
Paul Bakkerd8ee8442012-05-16 08:02:29 +00001570 if( neg )
1571 {
1572 X->s = -1;
1573 mpi_add_mpi( X, N, X );
1574 }
1575
Paul Bakker5121ce52009-01-03 21:22:43 +00001576cleanup:
1577
Paul Bakker23986e52011-04-24 08:57:21 +00001578 for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001579 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001580
Paul Bakkerd8ee8442012-05-16 08:02:29 +00001581 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001582
1583 if( _RR == NULL )
1584 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001585
1586 return( ret );
1587}
1588
Paul Bakker5121ce52009-01-03 21:22:43 +00001589/*
1590 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1591 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001592int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001593{
Paul Bakker23986e52011-04-24 08:57:21 +00001594 int ret;
1595 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001596 mpi TG, TA, TB;
1597
Paul Bakker6c591fa2011-05-05 11:49:20 +00001598 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001599
Paul Bakker5121ce52009-01-03 21:22:43 +00001600 MPI_CHK( mpi_copy( &TA, A ) );
1601 MPI_CHK( mpi_copy( &TB, B ) );
1602
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001603 lz = mpi_lsb( &TA );
1604 lzt = mpi_lsb( &TB );
1605
1606 if ( lzt < lz )
1607 lz = lzt;
1608
1609 MPI_CHK( mpi_shift_r( &TA, lz ) );
1610 MPI_CHK( mpi_shift_r( &TB, lz ) );
1611
Paul Bakker5121ce52009-01-03 21:22:43 +00001612 TA.s = TB.s = 1;
1613
1614 while( mpi_cmp_int( &TA, 0 ) != 0 )
1615 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001616 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1617 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001618
1619 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1620 {
1621 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1622 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1623 }
1624 else
1625 {
1626 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1627 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1628 }
1629 }
1630
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001631 MPI_CHK( mpi_shift_l( &TB, lz ) );
1632 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001633
1634cleanup:
1635
Paul Bakker6c591fa2011-05-05 11:49:20 +00001636 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001637
1638 return( ret );
1639}
1640
Paul Bakkera3d195c2011-11-27 21:07:34 +00001641int mpi_fill_random( mpi *X, size_t size,
1642 int (*f_rng)(void *, unsigned char *, size_t),
1643 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001644{
Paul Bakker23986e52011-04-24 08:57:21 +00001645 int ret;
Paul Bakker287781a2011-03-26 13:18:49 +00001646
Paul Bakker662d1682012-04-29 20:15:55 +00001647 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001648 MPI_CHK( mpi_lset( X, 0 ) );
1649
Paul Bakker662d1682012-04-29 20:15:55 +00001650 MPI_CHK( f_rng( p_rng, (unsigned char *) X->p, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001651
1652cleanup:
1653 return( ret );
1654}
1655
Paul Bakker5121ce52009-01-03 21:22:43 +00001656/*
1657 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1658 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001659int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001660{
1661 int ret;
1662 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1663
1664 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001665 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001666
Paul Bakker6c591fa2011-05-05 11:49:20 +00001667 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1668 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1669 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001670
1671 MPI_CHK( mpi_gcd( &G, A, N ) );
1672
1673 if( mpi_cmp_int( &G, 1 ) != 0 )
1674 {
Paul Bakker40e46942009-01-03 21:51:57 +00001675 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001676 goto cleanup;
1677 }
1678
1679 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1680 MPI_CHK( mpi_copy( &TU, &TA ) );
1681 MPI_CHK( mpi_copy( &TB, N ) );
1682 MPI_CHK( mpi_copy( &TV, N ) );
1683
1684 MPI_CHK( mpi_lset( &U1, 1 ) );
1685 MPI_CHK( mpi_lset( &U2, 0 ) );
1686 MPI_CHK( mpi_lset( &V1, 0 ) );
1687 MPI_CHK( mpi_lset( &V2, 1 ) );
1688
1689 do
1690 {
1691 while( ( TU.p[0] & 1 ) == 0 )
1692 {
1693 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1694
1695 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1696 {
1697 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1698 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1699 }
1700
1701 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1702 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1703 }
1704
1705 while( ( TV.p[0] & 1 ) == 0 )
1706 {
1707 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1708
1709 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1710 {
1711 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1712 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1713 }
1714
1715 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1716 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1717 }
1718
1719 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1720 {
1721 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1722 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1723 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1724 }
1725 else
1726 {
1727 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1728 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1729 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1730 }
1731 }
1732 while( mpi_cmp_int( &TU, 0 ) != 0 );
1733
1734 while( mpi_cmp_int( &V1, 0 ) < 0 )
1735 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1736
1737 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1738 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1739
1740 MPI_CHK( mpi_copy( X, &V1 ) );
1741
1742cleanup:
1743
Paul Bakker6c591fa2011-05-05 11:49:20 +00001744 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1745 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1746 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001747
1748 return( ret );
1749}
1750
Paul Bakker087e0372013-01-14 17:57:13 +01001751#if defined(POLARSSL_GENPRIME)
1752
Paul Bakker5121ce52009-01-03 21:22:43 +00001753static const int small_prime[] =
1754{
1755 3, 5, 7, 11, 13, 17, 19, 23,
1756 29, 31, 37, 41, 43, 47, 53, 59,
1757 61, 67, 71, 73, 79, 83, 89, 97,
1758 101, 103, 107, 109, 113, 127, 131, 137,
1759 139, 149, 151, 157, 163, 167, 173, 179,
1760 181, 191, 193, 197, 199, 211, 223, 227,
1761 229, 233, 239, 241, 251, 257, 263, 269,
1762 271, 277, 281, 283, 293, 307, 311, 313,
1763 317, 331, 337, 347, 349, 353, 359, 367,
1764 373, 379, 383, 389, 397, 401, 409, 419,
1765 421, 431, 433, 439, 443, 449, 457, 461,
1766 463, 467, 479, 487, 491, 499, 503, 509,
1767 521, 523, 541, 547, 557, 563, 569, 571,
1768 577, 587, 593, 599, 601, 607, 613, 617,
1769 619, 631, 641, 643, 647, 653, 659, 661,
1770 673, 677, 683, 691, 701, 709, 719, 727,
1771 733, 739, 743, 751, 757, 761, 769, 773,
1772 787, 797, 809, 811, 821, 823, 827, 829,
1773 839, 853, 857, 859, 863, 877, 881, 883,
1774 887, 907, 911, 919, 929, 937, 941, 947,
1775 953, 967, 971, 977, 983, 991, 997, -103
1776};
1777
1778/*
1779 * Miller-Rabin primality test (HAC 4.24)
1780 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001781int mpi_is_prime( mpi *X,
1782 int (*f_rng)(void *, unsigned char *, size_t),
1783 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001784{
Paul Bakker23986e52011-04-24 08:57:21 +00001785 int ret, xs;
1786 size_t i, j, n, s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001787 mpi W, R, T, A, RR;
Paul Bakker5121ce52009-01-03 21:22:43 +00001788
Paul Bakker48eab262009-06-25 21:25:49 +00001789 if( mpi_cmp_int( X, 0 ) == 0 ||
1790 mpi_cmp_int( X, 1 ) == 0 )
1791 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1792
1793 if( mpi_cmp_int( X, 2 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001794 return( 0 );
1795
Paul Bakker6c591fa2011-05-05 11:49:20 +00001796 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
1797 mpi_init( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001798
1799 xs = X->s; X->s = 1;
1800
1801 /*
1802 * test trivial factors first
1803 */
1804 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001805 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001806
1807 for( i = 0; small_prime[i] > 0; i++ )
1808 {
Paul Bakkera755ca12011-04-24 09:11:17 +00001809 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001810
1811 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
1812 return( 0 );
1813
1814 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1815
1816 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001817 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001818 }
1819
1820 /*
1821 * W = |X| - 1
1822 * R = W >> lsb( W )
1823 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001824 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001825 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001826 MPI_CHK( mpi_copy( &R, &W ) );
1827 MPI_CHK( mpi_shift_r( &R, s ) );
1828
1829 i = mpi_msb( X );
1830 /*
1831 * HAC, table 4.4
1832 */
1833 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1834 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1835 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1836
1837 for( i = 0; i < n; i++ )
1838 {
1839 /*
1840 * pick a random A, 1 < A < |X| - 1
1841 */
Paul Bakkere2f8ff62012-04-20 13:33:14 +00001842 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001843
Paul Bakkerb94081b2011-01-05 15:53:06 +00001844 if( mpi_cmp_mpi( &A, &W ) >= 0 )
1845 {
1846 j = mpi_msb( &A ) - mpi_msb( &W );
1847 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1848 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001849 A.p[0] |= 3;
1850
1851 /*
1852 * A = A^R mod |X|
1853 */
1854 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1855
1856 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1857 mpi_cmp_int( &A, 1 ) == 0 )
1858 continue;
1859
1860 j = 1;
1861 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1862 {
1863 /*
1864 * A = A * A mod |X|
1865 */
1866 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1867 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1868
1869 if( mpi_cmp_int( &A, 1 ) == 0 )
1870 break;
1871
1872 j++;
1873 }
1874
1875 /*
1876 * not prime if A != |X| - 1 or A == 1
1877 */
1878 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1879 mpi_cmp_int( &A, 1 ) == 0 )
1880 {
Paul Bakker40e46942009-01-03 21:51:57 +00001881 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001882 break;
1883 }
1884 }
1885
1886cleanup:
1887
1888 X->s = xs;
1889
Paul Bakker6c591fa2011-05-05 11:49:20 +00001890 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
1891 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001892
1893 return( ret );
1894}
1895
1896/*
1897 * Prime number generation
1898 */
Paul Bakker23986e52011-04-24 08:57:21 +00001899int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001900 int (*f_rng)(void *, unsigned char *, size_t),
1901 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001902{
Paul Bakker23986e52011-04-24 08:57:21 +00001903 int ret;
1904 size_t k, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001905 mpi Y;
1906
Paul Bakkerfe3256e2011-11-25 12:11:43 +00001907 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00001908 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001909
Paul Bakker6c591fa2011-05-05 11:49:20 +00001910 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001911
1912 n = BITS_TO_LIMBS( nbits );
1913
Paul Bakkere2f8ff62012-04-20 13:33:14 +00001914 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001915
1916 k = mpi_msb( X );
1917 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
1918 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
1919
1920 X->p[0] |= 3;
1921
1922 if( dh_flag == 0 )
1923 {
1924 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
1925 {
Paul Bakker40e46942009-01-03 21:51:57 +00001926 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001927 goto cleanup;
1928
1929 MPI_CHK( mpi_add_int( X, X, 2 ) );
1930 }
1931 }
1932 else
1933 {
1934 MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
1935 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1936
1937 while( 1 )
1938 {
1939 if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
1940 {
1941 if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
1942 break;
1943
Paul Bakker40e46942009-01-03 21:51:57 +00001944 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001945 goto cleanup;
1946 }
1947
Paul Bakker40e46942009-01-03 21:51:57 +00001948 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001949 goto cleanup;
1950
1951 MPI_CHK( mpi_add_int( &Y, X, 1 ) );
1952 MPI_CHK( mpi_add_int( X, X, 2 ) );
1953 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1954 }
1955 }
1956
1957cleanup:
1958
Paul Bakker6c591fa2011-05-05 11:49:20 +00001959 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001960
1961 return( ret );
1962}
1963
1964#endif
1965
Paul Bakker40e46942009-01-03 21:51:57 +00001966#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00001967
Paul Bakker23986e52011-04-24 08:57:21 +00001968#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001969
1970static const int gcd_pairs[GCD_PAIR_COUNT][3] =
1971{
1972 { 693, 609, 21 },
1973 { 1764, 868, 28 },
1974 { 768454923, 542167814, 1 }
1975};
1976
Paul Bakker5121ce52009-01-03 21:22:43 +00001977/*
1978 * Checkup routine
1979 */
1980int mpi_self_test( int verbose )
1981{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001982 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001983 mpi A, E, N, X, Y, U, V;
1984
Paul Bakker6c591fa2011-05-05 11:49:20 +00001985 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
1986 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00001987
1988 MPI_CHK( mpi_read_string( &A, 16,
1989 "EFE021C2645FD1DC586E69184AF4A31E" \
1990 "D5F53E93B5F123FA41680867BA110131" \
1991 "944FE7952E2517337780CB0DB80E61AA" \
1992 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
1993
1994 MPI_CHK( mpi_read_string( &E, 16,
1995 "B2E7EFD37075B9F03FF989C7C5051C20" \
1996 "34D2A323810251127E7BF8625A4F49A5" \
1997 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
1998 "5B5C25763222FEFCCFC38B832366C29E" ) );
1999
2000 MPI_CHK( mpi_read_string( &N, 16,
2001 "0066A198186C18C10B2F5ED9B522752A" \
2002 "9830B69916E535C8F047518A889A43A5" \
2003 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2004
2005 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2006
2007 MPI_CHK( mpi_read_string( &U, 16,
2008 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2009 "9E857EA95A03512E2BAE7391688D264A" \
2010 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2011 "8001B72E848A38CAE1C65F78E56ABDEF" \
2012 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2013 "ECF677152EF804370C1A305CAF3B5BF1" \
2014 "30879B56C61DE584A0F53A2447A51E" ) );
2015
2016 if( verbose != 0 )
2017 printf( " MPI test #1 (mul_mpi): " );
2018
2019 if( mpi_cmp_mpi( &X, &U ) != 0 )
2020 {
2021 if( verbose != 0 )
2022 printf( "failed\n" );
2023
2024 return( 1 );
2025 }
2026
2027 if( verbose != 0 )
2028 printf( "passed\n" );
2029
2030 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2031
2032 MPI_CHK( mpi_read_string( &U, 16,
2033 "256567336059E52CAE22925474705F39A94" ) );
2034
2035 MPI_CHK( mpi_read_string( &V, 16,
2036 "6613F26162223DF488E9CD48CC132C7A" \
2037 "0AC93C701B001B092E4E5B9F73BCD27B" \
2038 "9EE50D0657C77F374E903CDFA4C642" ) );
2039
2040 if( verbose != 0 )
2041 printf( " MPI test #2 (div_mpi): " );
2042
2043 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2044 mpi_cmp_mpi( &Y, &V ) != 0 )
2045 {
2046 if( verbose != 0 )
2047 printf( "failed\n" );
2048
2049 return( 1 );
2050 }
2051
2052 if( verbose != 0 )
2053 printf( "passed\n" );
2054
2055 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2056
2057 MPI_CHK( mpi_read_string( &U, 16,
2058 "36E139AEA55215609D2816998ED020BB" \
2059 "BD96C37890F65171D948E9BC7CBAA4D9" \
2060 "325D24D6A3C12710F10A09FA08AB87" ) );
2061
2062 if( verbose != 0 )
2063 printf( " MPI test #3 (exp_mod): " );
2064
2065 if( mpi_cmp_mpi( &X, &U ) != 0 )
2066 {
2067 if( verbose != 0 )
2068 printf( "failed\n" );
2069
2070 return( 1 );
2071 }
2072
2073 if( verbose != 0 )
2074 printf( "passed\n" );
2075
Paul Bakker5690efc2011-05-26 13:16:06 +00002076#if defined(POLARSSL_GENPRIME)
Paul Bakker5121ce52009-01-03 21:22:43 +00002077 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2078
2079 MPI_CHK( mpi_read_string( &U, 16,
2080 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2081 "C3DBA76456363A10869622EAC2DD84EC" \
2082 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2083
2084 if( verbose != 0 )
2085 printf( " MPI test #4 (inv_mod): " );
2086
2087 if( mpi_cmp_mpi( &X, &U ) != 0 )
2088 {
2089 if( verbose != 0 )
2090 printf( "failed\n" );
2091
2092 return( 1 );
2093 }
2094
2095 if( verbose != 0 )
2096 printf( "passed\n" );
Paul Bakker5690efc2011-05-26 13:16:06 +00002097#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002098
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002099 if( verbose != 0 )
2100 printf( " MPI test #5 (simple gcd): " );
2101
2102 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2103 {
2104 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002105 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002106
Paul Bakker23986e52011-04-24 08:57:21 +00002107 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002108
Paul Bakker23986e52011-04-24 08:57:21 +00002109 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2110 {
2111 if( verbose != 0 )
2112 printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002113
Paul Bakker23986e52011-04-24 08:57:21 +00002114 return( 1 );
2115 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002116 }
2117
2118 if( verbose != 0 )
2119 printf( "passed\n" );
2120
Paul Bakker5121ce52009-01-03 21:22:43 +00002121cleanup:
2122
2123 if( ret != 0 && verbose != 0 )
2124 printf( "Unexpected error, return code = %08X\n", ret );
2125
Paul Bakker6c591fa2011-05-05 11:49:20 +00002126 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2127 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002128
2129 if( verbose != 0 )
2130 printf( "\n" );
2131
2132 return( ret );
2133}
2134
2135#endif
2136
2137#endif