blob: 9af6980c6e645f7269fa61ed6a3e822378439390 [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 Bakker69e095c2011-12-10 21:55:01 +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 Bakker69e095c2011-12-10 21:55:01 +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 */
Paul Bakker6b906e52012-05-08 12:01:43 +0000176int mpi_get_bit( const mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000177{
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
612 /*
613 * shift by count / limb_size
614 */
615 if( v0 > 0 )
616 {
617 for( i = 0; i < X->n - v0; i++ )
618 X->p[i] = X->p[i + v0];
619
620 for( ; i < X->n; i++ )
621 X->p[i] = 0;
622 }
623
624 /*
625 * shift by count % limb_size
626 */
627 if( v1 > 0 )
628 {
Paul Bakker23986e52011-04-24 08:57:21 +0000629 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000630 {
Paul Bakker23986e52011-04-24 08:57:21 +0000631 r1 = X->p[i - 1] << (biL - v1);
632 X->p[i - 1] >>= v1;
633 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000634 r0 = r1;
635 }
636 }
637
638 return( 0 );
639}
640
641/*
642 * Compare unsigned values
643 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000644int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000645{
Paul Bakker23986e52011-04-24 08:57:21 +0000646 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000647
Paul Bakker23986e52011-04-24 08:57:21 +0000648 for( i = X->n; i > 0; i-- )
649 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000650 break;
651
Paul Bakker23986e52011-04-24 08:57:21 +0000652 for( j = Y->n; j > 0; j-- )
653 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000654 break;
655
Paul Bakker23986e52011-04-24 08:57:21 +0000656 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000657 return( 0 );
658
659 if( i > j ) return( 1 );
660 if( j > i ) return( -1 );
661
Paul Bakker23986e52011-04-24 08:57:21 +0000662 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000663 {
Paul Bakker23986e52011-04-24 08:57:21 +0000664 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
665 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000666 }
667
668 return( 0 );
669}
670
671/*
672 * Compare signed values
673 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000674int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000675{
Paul Bakker23986e52011-04-24 08:57:21 +0000676 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000677
Paul Bakker23986e52011-04-24 08:57:21 +0000678 for( i = X->n; i > 0; i-- )
679 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000680 break;
681
Paul Bakker23986e52011-04-24 08:57:21 +0000682 for( j = Y->n; j > 0; j-- )
683 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000684 break;
685
Paul Bakker23986e52011-04-24 08:57:21 +0000686 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000687 return( 0 );
688
689 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000690 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
692 if( X->s > 0 && Y->s < 0 ) return( 1 );
693 if( Y->s > 0 && X->s < 0 ) return( -1 );
694
Paul Bakker23986e52011-04-24 08:57:21 +0000695 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000696 {
Paul Bakker23986e52011-04-24 08:57:21 +0000697 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
698 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000699 }
700
701 return( 0 );
702}
703
704/*
705 * Compare signed values
706 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000707int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000708{
709 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000710 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
712 *p = ( z < 0 ) ? -z : z;
713 Y.s = ( z < 0 ) ? -1 : 1;
714 Y.n = 1;
715 Y.p = p;
716
717 return( mpi_cmp_mpi( X, &Y ) );
718}
719
720/*
721 * Unsigned addition: X = |A| + |B| (HAC 14.7)
722 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000723int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000724{
Paul Bakker23986e52011-04-24 08:57:21 +0000725 int ret;
726 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000727 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000728
729 if( X == B )
730 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000731 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000732 }
733
734 if( X != A )
735 MPI_CHK( mpi_copy( X, A ) );
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000736
737 /*
738 * X should always be positive as a result of unsigned additions.
739 */
740 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000741
Paul Bakker23986e52011-04-24 08:57:21 +0000742 for( j = B->n; j > 0; j-- )
743 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000744 break;
745
Paul Bakker23986e52011-04-24 08:57:21 +0000746 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000747
748 o = B->p; p = X->p; c = 0;
749
Paul Bakker23986e52011-04-24 08:57:21 +0000750 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000751 {
752 *p += c; c = ( *p < c );
753 *p += *o; c += ( *p < *o );
754 }
755
756 while( c != 0 )
757 {
758 if( i >= X->n )
759 {
760 MPI_CHK( mpi_grow( X, i + 1 ) );
761 p = X->p + i;
762 }
763
Paul Bakker2d319fd2012-09-16 21:34:26 +0000764 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000765 }
766
767cleanup:
768
769 return( ret );
770}
771
772/*
773 * Helper for mpi substraction
774 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000775static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000776{
Paul Bakker23986e52011-04-24 08:57:21 +0000777 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000778 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000779
780 for( i = c = 0; i < n; i++, s++, d++ )
781 {
782 z = ( *d < c ); *d -= c;
783 c = ( *d < *s ) + z; *d -= *s;
784 }
785
786 while( c != 0 )
787 {
788 z = ( *d < c ); *d -= c;
789 c = z; i++; d++;
790 }
791}
792
793/*
794 * Unsigned substraction: X = |A| - |B| (HAC 14.9)
795 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000796int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000797{
798 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000799 int ret;
800 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000801
802 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000803 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000804
Paul Bakker6c591fa2011-05-05 11:49:20 +0000805 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000806
807 if( X == B )
808 {
809 MPI_CHK( mpi_copy( &TB, B ) );
810 B = &TB;
811 }
812
813 if( X != A )
814 MPI_CHK( mpi_copy( X, A ) );
815
Paul Bakker1ef7a532009-06-20 10:50:55 +0000816 /*
817 * X should always be positive as a result of unsigned substractions.
818 */
819 X->s = 1;
820
Paul Bakker5121ce52009-01-03 21:22:43 +0000821 ret = 0;
822
Paul Bakker23986e52011-04-24 08:57:21 +0000823 for( n = B->n; n > 0; n-- )
824 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000825 break;
826
Paul Bakker23986e52011-04-24 08:57:21 +0000827 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000828
829cleanup:
830
Paul Bakker6c591fa2011-05-05 11:49:20 +0000831 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000832
833 return( ret );
834}
835
836/*
837 * Signed addition: X = A + B
838 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000839int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000840{
841 int ret, s = A->s;
842
843 if( A->s * B->s < 0 )
844 {
845 if( mpi_cmp_abs( A, B ) >= 0 )
846 {
847 MPI_CHK( mpi_sub_abs( X, A, B ) );
848 X->s = s;
849 }
850 else
851 {
852 MPI_CHK( mpi_sub_abs( X, B, A ) );
853 X->s = -s;
854 }
855 }
856 else
857 {
858 MPI_CHK( mpi_add_abs( X, A, B ) );
859 X->s = s;
860 }
861
862cleanup:
863
864 return( ret );
865}
866
867/*
868 * Signed substraction: X = A - B
869 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000870int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000871{
872 int ret, s = A->s;
873
874 if( A->s * B->s > 0 )
875 {
876 if( mpi_cmp_abs( A, B ) >= 0 )
877 {
878 MPI_CHK( mpi_sub_abs( X, A, B ) );
879 X->s = s;
880 }
881 else
882 {
883 MPI_CHK( mpi_sub_abs( X, B, A ) );
884 X->s = -s;
885 }
886 }
887 else
888 {
889 MPI_CHK( mpi_add_abs( X, A, B ) );
890 X->s = s;
891 }
892
893cleanup:
894
895 return( ret );
896}
897
898/*
899 * Signed addition: X = A + b
900 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000901int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000902{
903 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000904 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000905
906 p[0] = ( b < 0 ) ? -b : b;
907 _B.s = ( b < 0 ) ? -1 : 1;
908 _B.n = 1;
909 _B.p = p;
910
911 return( mpi_add_mpi( X, A, &_B ) );
912}
913
914/*
915 * Signed substraction: X = A - b
916 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000917int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000918{
919 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000920 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000921
922 p[0] = ( b < 0 ) ? -b : b;
923 _B.s = ( b < 0 ) ? -1 : 1;
924 _B.n = 1;
925 _B.p = p;
926
927 return( mpi_sub_mpi( X, A, &_B ) );
928}
929
930/*
931 * Helper for mpi multiplication
932 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000933static void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000934{
Paul Bakkera755ca12011-04-24 09:11:17 +0000935 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000936
937#if defined(MULADDC_HUIT)
938 for( ; i >= 8; i -= 8 )
939 {
940 MULADDC_INIT
941 MULADDC_HUIT
942 MULADDC_STOP
943 }
944
945 for( ; i > 0; i-- )
946 {
947 MULADDC_INIT
948 MULADDC_CORE
949 MULADDC_STOP
950 }
951#else
952 for( ; i >= 16; i -= 16 )
953 {
954 MULADDC_INIT
955 MULADDC_CORE MULADDC_CORE
956 MULADDC_CORE MULADDC_CORE
957 MULADDC_CORE MULADDC_CORE
958 MULADDC_CORE MULADDC_CORE
959
960 MULADDC_CORE MULADDC_CORE
961 MULADDC_CORE MULADDC_CORE
962 MULADDC_CORE MULADDC_CORE
963 MULADDC_CORE MULADDC_CORE
964 MULADDC_STOP
965 }
966
967 for( ; i >= 8; i -= 8 )
968 {
969 MULADDC_INIT
970 MULADDC_CORE MULADDC_CORE
971 MULADDC_CORE MULADDC_CORE
972
973 MULADDC_CORE MULADDC_CORE
974 MULADDC_CORE MULADDC_CORE
975 MULADDC_STOP
976 }
977
978 for( ; i > 0; i-- )
979 {
980 MULADDC_INIT
981 MULADDC_CORE
982 MULADDC_STOP
983 }
984#endif
985
986 t++;
987
988 do {
989 *d += c; c = ( *d < c ); d++;
990 }
991 while( c != 0 );
992}
993
994/*
995 * Baseline multiplication: X = A * B (HAC 14.12)
996 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000997int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000998{
Paul Bakker23986e52011-04-24 08:57:21 +0000999 int ret;
1000 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001001 mpi TA, TB;
1002
Paul Bakker6c591fa2011-05-05 11:49:20 +00001003 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001004
1005 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1006 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1007
Paul Bakker23986e52011-04-24 08:57:21 +00001008 for( i = A->n; i > 0; i-- )
1009 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001010 break;
1011
Paul Bakker23986e52011-04-24 08:57:21 +00001012 for( j = B->n; j > 0; j-- )
1013 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001014 break;
1015
Paul Bakker23986e52011-04-24 08:57:21 +00001016 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001017 MPI_CHK( mpi_lset( X, 0 ) );
1018
Paul Bakker23986e52011-04-24 08:57:21 +00001019 for( i++; j > 0; j-- )
1020 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001021
1022 X->s = A->s * B->s;
1023
1024cleanup:
1025
Paul Bakker6c591fa2011-05-05 11:49:20 +00001026 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001027
1028 return( ret );
1029}
1030
1031/*
1032 * Baseline multiplication: X = A * b
1033 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001034int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001035{
1036 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001037 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001038
1039 _B.s = 1;
1040 _B.n = 1;
1041 _B.p = p;
1042 p[0] = b;
1043
1044 return( mpi_mul_mpi( X, A, &_B ) );
1045}
1046
1047/*
1048 * Division by mpi: A = Q * B + R (HAC 14.20)
1049 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001050int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001051{
Paul Bakker23986e52011-04-24 08:57:21 +00001052 int ret;
1053 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001054 mpi X, Y, Z, T1, T2;
1055
1056 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001057 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001058
Paul Bakker6c591fa2011-05-05 11:49:20 +00001059 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1060 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001061
1062 if( mpi_cmp_abs( A, B ) < 0 )
1063 {
1064 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1065 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1066 return( 0 );
1067 }
1068
1069 MPI_CHK( mpi_copy( &X, A ) );
1070 MPI_CHK( mpi_copy( &Y, B ) );
1071 X.s = Y.s = 1;
1072
1073 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1074 MPI_CHK( mpi_lset( &Z, 0 ) );
1075 MPI_CHK( mpi_grow( &T1, 2 ) );
1076 MPI_CHK( mpi_grow( &T2, 3 ) );
1077
1078 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001079 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001080 {
1081 k = biL - 1 - k;
1082 MPI_CHK( mpi_shift_l( &X, k ) );
1083 MPI_CHK( mpi_shift_l( &Y, k ) );
1084 }
1085 else k = 0;
1086
1087 n = X.n - 1;
1088 t = Y.n - 1;
1089 mpi_shift_l( &Y, biL * (n - t) );
1090
1091 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1092 {
1093 Z.p[n - t]++;
1094 mpi_sub_mpi( &X, &X, &Y );
1095 }
1096 mpi_shift_r( &Y, biL * (n - t) );
1097
1098 for( i = n; i > t ; i-- )
1099 {
1100 if( X.p[i] >= Y.p[t] )
1101 Z.p[i - t - 1] = ~0;
1102 else
1103 {
Paul Bakker17caec12012-01-22 20:37:32 +00001104#if defined(POLARSSL_HAVE_LONGLONG)
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001105 t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001106
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001107 r = (t_udbl) X.p[i] << biL;
1108 r |= (t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001109 r /= Y.p[t];
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001110 if( r > ((t_udbl) 1 << biL) - 1)
1111 r = ((t_udbl) 1 << biL) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001112
Paul Bakkera755ca12011-04-24 09:11:17 +00001113 Z.p[i - t - 1] = (t_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001114#else
1115 /*
1116 * __udiv_qrnnd_c, from gmp/longlong.h
1117 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001118 t_uint q0, q1, r0, r1;
1119 t_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001120
1121 d = Y.p[t];
1122 d0 = ( d << biH ) >> biH;
1123 d1 = ( d >> biH );
1124
1125 q1 = X.p[i] / d1;
1126 r1 = X.p[i] - d1 * q1;
1127 r1 <<= biH;
1128 r1 |= ( X.p[i - 1] >> biH );
1129
1130 m = q1 * d0;
1131 if( r1 < m )
1132 {
1133 q1--, r1 += d;
1134 while( r1 >= d && r1 < m )
1135 q1--, r1 += d;
1136 }
1137 r1 -= m;
1138
1139 q0 = r1 / d1;
1140 r0 = r1 - d1 * q0;
1141 r0 <<= biH;
1142 r0 |= ( X.p[i - 1] << biH ) >> biH;
1143
1144 m = q0 * d0;
1145 if( r0 < m )
1146 {
1147 q0--, r0 += d;
1148 while( r0 >= d && r0 < m )
1149 q0--, r0 += d;
1150 }
1151 r0 -= m;
1152
1153 Z.p[i - t - 1] = ( q1 << biH ) | q0;
1154#endif
1155 }
1156
1157 Z.p[i - t - 1]++;
1158 do
1159 {
1160 Z.p[i - t - 1]--;
1161
1162 MPI_CHK( mpi_lset( &T1, 0 ) );
1163 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1164 T1.p[1] = Y.p[t];
1165 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1166
1167 MPI_CHK( mpi_lset( &T2, 0 ) );
1168 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1169 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1170 T2.p[2] = X.p[i];
1171 }
1172 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1173
1174 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1175 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1176 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1177
1178 if( mpi_cmp_int( &X, 0 ) < 0 )
1179 {
1180 MPI_CHK( mpi_copy( &T1, &Y ) );
1181 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1182 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1183 Z.p[i - t - 1]--;
1184 }
1185 }
1186
1187 if( Q != NULL )
1188 {
1189 mpi_copy( Q, &Z );
1190 Q->s = A->s * B->s;
1191 }
1192
1193 if( R != NULL )
1194 {
1195 mpi_shift_r( &X, k );
1196 mpi_copy( R, &X );
1197
1198 R->s = A->s;
1199 if( mpi_cmp_int( R, 0 ) == 0 )
1200 R->s = 1;
1201 }
1202
1203cleanup:
1204
Paul Bakker6c591fa2011-05-05 11:49:20 +00001205 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1206 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001207
1208 return( ret );
1209}
1210
1211/*
1212 * Division by int: A = Q * b + R
1213 *
1214 * Returns 0 if successful
1215 * 1 if memory allocation failed
Paul Bakker40e46942009-01-03 21:51:57 +00001216 * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
Paul Bakker5121ce52009-01-03 21:22:43 +00001217 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001218int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001219{
1220 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001221 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001222
1223 p[0] = ( b < 0 ) ? -b : b;
1224 _B.s = ( b < 0 ) ? -1 : 1;
1225 _B.n = 1;
1226 _B.p = p;
1227
1228 return( mpi_div_mpi( Q, R, A, &_B ) );
1229}
1230
1231/*
1232 * Modulo: R = A mod B
1233 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001234int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001235{
1236 int ret;
1237
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001238 if( mpi_cmp_int( B, 0 ) < 0 )
1239 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1240
Paul Bakker5121ce52009-01-03 21:22:43 +00001241 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1242
1243 while( mpi_cmp_int( R, 0 ) < 0 )
1244 MPI_CHK( mpi_add_mpi( R, R, B ) );
1245
1246 while( mpi_cmp_mpi( R, B ) >= 0 )
1247 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1248
1249cleanup:
1250
1251 return( ret );
1252}
1253
1254/*
1255 * Modulo: r = A mod b
1256 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001257int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001258{
Paul Bakker23986e52011-04-24 08:57:21 +00001259 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001260 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001261
1262 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001263 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001264
1265 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001266 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001267
1268 /*
1269 * handle trivial cases
1270 */
1271 if( b == 1 )
1272 {
1273 *r = 0;
1274 return( 0 );
1275 }
1276
1277 if( b == 2 )
1278 {
1279 *r = A->p[0] & 1;
1280 return( 0 );
1281 }
1282
1283 /*
1284 * general case
1285 */
Paul Bakker23986e52011-04-24 08:57:21 +00001286 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001287 {
Paul Bakker23986e52011-04-24 08:57:21 +00001288 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001289 y = ( y << biH ) | ( x >> biH );
1290 z = y / b;
1291 y -= z * b;
1292
1293 x <<= biH;
1294 y = ( y << biH ) | ( x >> biH );
1295 z = y / b;
1296 y -= z * b;
1297 }
1298
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001299 /*
1300 * If A is negative, then the current y represents a negative value.
1301 * Flipping it to the positive side.
1302 */
1303 if( A->s < 0 && y != 0 )
1304 y = b - y;
1305
Paul Bakker5121ce52009-01-03 21:22:43 +00001306 *r = y;
1307
1308 return( 0 );
1309}
1310
1311/*
1312 * Fast Montgomery initialization (thanks to Tom St Denis)
1313 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001314static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001315{
Paul Bakkera755ca12011-04-24 09:11:17 +00001316 t_uint x, m0 = N->p[0];
Paul Bakker5121ce52009-01-03 21:22:43 +00001317
1318 x = m0;
1319 x += ( ( m0 + 2 ) & 4 ) << 1;
1320 x *= ( 2 - ( m0 * x ) );
1321
1322 if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
1323 if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
1324 if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
1325
1326 *mm = ~x + 1;
1327}
1328
1329/*
1330 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1331 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001332static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001333{
Paul Bakker23986e52011-04-24 08:57:21 +00001334 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001335 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001336
1337 memset( T->p, 0, T->n * ciL );
1338
1339 d = T->p;
1340 n = N->n;
1341 m = ( B->n < n ) ? B->n : n;
1342
1343 for( i = 0; i < n; i++ )
1344 {
1345 /*
1346 * T = (T + u0*B + u1*N) / 2^biL
1347 */
1348 u0 = A->p[i];
1349 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1350
1351 mpi_mul_hlp( m, B->p, d, u0 );
1352 mpi_mul_hlp( n, N->p, d, u1 );
1353
1354 *d++ = u0; d[n + 1] = 0;
1355 }
1356
1357 memcpy( A->p, d, (n + 1) * ciL );
1358
1359 if( mpi_cmp_abs( A, N ) >= 0 )
1360 mpi_sub_hlp( n, N->p, A->p );
1361 else
1362 /* prevent timing attacks */
1363 mpi_sub_hlp( n, A->p, T->p );
1364}
1365
1366/*
1367 * Montgomery reduction: A = A * R^-1 mod N
1368 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001369static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001370{
Paul Bakkera755ca12011-04-24 09:11:17 +00001371 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001372 mpi U;
1373
1374 U.n = U.s = z;
1375 U.p = &z;
1376
1377 mpi_montmul( A, &U, N, mm, T );
1378}
1379
1380/*
1381 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1382 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001383int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001384{
Paul Bakker23986e52011-04-24 08:57:21 +00001385 int ret;
1386 size_t wbits, wsize, one = 1;
1387 size_t i, j, nblimbs;
1388 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001389 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001390 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1391 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001392
1393 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001394 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001395
Paul Bakkerf6198c12012-05-16 08:02:29 +00001396 if( mpi_cmp_int( E, 0 ) < 0 )
1397 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1398
1399 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001400 * Init temps and window size
1401 */
1402 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001403 mpi_init( &RR ); mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001404 memset( W, 0, sizeof( W ) );
1405
1406 i = mpi_msb( E );
1407
1408 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1409 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1410
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001411 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1412 wsize = POLARSSL_MPI_WINDOW_SIZE;
1413
Paul Bakker5121ce52009-01-03 21:22:43 +00001414 j = N->n + 1;
1415 MPI_CHK( mpi_grow( X, j ) );
1416 MPI_CHK( mpi_grow( &W[1], j ) );
1417 MPI_CHK( mpi_grow( &T, j * 2 ) );
1418
1419 /*
Paul Bakker50546922012-05-19 08:40:49 +00001420 * Compensate for negative A (and correct at the end)
1421 */
1422 neg = ( A->s == -1 );
1423
1424 mpi_init( &Apos );
1425 if( neg )
1426 {
1427 MPI_CHK( mpi_copy( &Apos, A ) );
1428 Apos.s = 1;
1429 A = &Apos;
1430 }
1431
1432 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001433 * If 1st call, pre-compute R^2 mod N
1434 */
1435 if( _RR == NULL || _RR->p == NULL )
1436 {
1437 MPI_CHK( mpi_lset( &RR, 1 ) );
1438 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1439 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1440
1441 if( _RR != NULL )
1442 memcpy( _RR, &RR, sizeof( mpi ) );
1443 }
1444 else
1445 memcpy( &RR, _RR, sizeof( mpi ) );
1446
1447 /*
1448 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1449 */
1450 if( mpi_cmp_mpi( A, N ) >= 0 )
1451 mpi_mod_mpi( &W[1], A, N );
1452 else mpi_copy( &W[1], A );
1453
1454 mpi_montmul( &W[1], &RR, N, mm, &T );
1455
1456 /*
1457 * X = R^2 * R^-1 mod N = R mod N
1458 */
1459 MPI_CHK( mpi_copy( X, &RR ) );
1460 mpi_montred( X, N, mm, &T );
1461
1462 if( wsize > 1 )
1463 {
1464 /*
1465 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1466 */
Paul Bakker23986e52011-04-24 08:57:21 +00001467 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001468
1469 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1470 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1471
1472 for( i = 0; i < wsize - 1; i++ )
1473 mpi_montmul( &W[j], &W[j], N, mm, &T );
1474
1475 /*
1476 * W[i] = W[i - 1] * W[1]
1477 */
Paul Bakker23986e52011-04-24 08:57:21 +00001478 for( i = j + 1; i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001479 {
1480 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1481 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1482
1483 mpi_montmul( &W[i], &W[1], N, mm, &T );
1484 }
1485 }
1486
1487 nblimbs = E->n;
1488 bufsize = 0;
1489 nbits = 0;
1490 wbits = 0;
1491 state = 0;
1492
1493 while( 1 )
1494 {
1495 if( bufsize == 0 )
1496 {
1497 if( nblimbs-- == 0 )
1498 break;
1499
Paul Bakkera755ca12011-04-24 09:11:17 +00001500 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001501 }
1502
1503 bufsize--;
1504
1505 ei = (E->p[nblimbs] >> bufsize) & 1;
1506
1507 /*
1508 * skip leading 0s
1509 */
1510 if( ei == 0 && state == 0 )
1511 continue;
1512
1513 if( ei == 0 && state == 1 )
1514 {
1515 /*
1516 * out of window, square X
1517 */
1518 mpi_montmul( X, X, N, mm, &T );
1519 continue;
1520 }
1521
1522 /*
1523 * add ei to current window
1524 */
1525 state = 2;
1526
1527 nbits++;
1528 wbits |= (ei << (wsize - nbits));
1529
1530 if( nbits == wsize )
1531 {
1532 /*
1533 * X = X^wsize R^-1 mod N
1534 */
1535 for( i = 0; i < wsize; i++ )
1536 mpi_montmul( X, X, N, mm, &T );
1537
1538 /*
1539 * X = X * W[wbits] R^-1 mod N
1540 */
1541 mpi_montmul( X, &W[wbits], N, mm, &T );
1542
1543 state--;
1544 nbits = 0;
1545 wbits = 0;
1546 }
1547 }
1548
1549 /*
1550 * process the remaining bits
1551 */
1552 for( i = 0; i < nbits; i++ )
1553 {
1554 mpi_montmul( X, X, N, mm, &T );
1555
1556 wbits <<= 1;
1557
Paul Bakker23986e52011-04-24 08:57:21 +00001558 if( (wbits & (one << wsize)) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001559 mpi_montmul( X, &W[1], N, mm, &T );
1560 }
1561
1562 /*
1563 * X = A^E * R * R^-1 mod N = A^E mod N
1564 */
1565 mpi_montred( X, N, mm, &T );
1566
Paul Bakkerf6198c12012-05-16 08:02:29 +00001567 if( neg )
1568 {
1569 X->s = -1;
1570 mpi_add_mpi( X, N, X );
1571 }
1572
Paul Bakker5121ce52009-01-03 21:22:43 +00001573cleanup:
1574
Paul Bakker23986e52011-04-24 08:57:21 +00001575 for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001576 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001577
Paul Bakkerf6198c12012-05-16 08:02:29 +00001578 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001579
1580 if( _RR == NULL )
1581 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001582
1583 return( ret );
1584}
1585
Paul Bakker5121ce52009-01-03 21:22:43 +00001586/*
1587 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1588 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001589int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001590{
Paul Bakker23986e52011-04-24 08:57:21 +00001591 int ret;
1592 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001593 mpi TG, TA, TB;
1594
Paul Bakker6c591fa2011-05-05 11:49:20 +00001595 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001596
Paul Bakker5121ce52009-01-03 21:22:43 +00001597 MPI_CHK( mpi_copy( &TA, A ) );
1598 MPI_CHK( mpi_copy( &TB, B ) );
1599
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001600 lz = mpi_lsb( &TA );
1601 lzt = mpi_lsb( &TB );
1602
1603 if ( lzt < lz )
1604 lz = lzt;
1605
1606 MPI_CHK( mpi_shift_r( &TA, lz ) );
1607 MPI_CHK( mpi_shift_r( &TB, lz ) );
1608
Paul Bakker5121ce52009-01-03 21:22:43 +00001609 TA.s = TB.s = 1;
1610
1611 while( mpi_cmp_int( &TA, 0 ) != 0 )
1612 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001613 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1614 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001615
1616 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1617 {
1618 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1619 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1620 }
1621 else
1622 {
1623 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1624 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1625 }
1626 }
1627
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001628 MPI_CHK( mpi_shift_l( &TB, lz ) );
1629 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001630
1631cleanup:
1632
Paul Bakker6c591fa2011-05-05 11:49:20 +00001633 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001634
1635 return( ret );
1636}
1637
Paul Bakkera3d195c2011-11-27 21:07:34 +00001638int mpi_fill_random( mpi *X, size_t size,
1639 int (*f_rng)(void *, unsigned char *, size_t),
1640 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001641{
Paul Bakker23986e52011-04-24 08:57:21 +00001642 int ret;
Paul Bakker287781a2011-03-26 13:18:49 +00001643
Paul Bakker39dfdac2012-02-12 17:17:27 +00001644 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001645 MPI_CHK( mpi_lset( X, 0 ) );
1646
Paul Bakker39dfdac2012-02-12 17:17:27 +00001647 MPI_CHK( f_rng( p_rng, (unsigned char *) X->p, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001648
1649cleanup:
1650 return( ret );
1651}
1652
Paul Bakker70b3eed2009-03-14 18:01:25 +00001653#if defined(POLARSSL_GENPRIME)
1654
Paul Bakker5121ce52009-01-03 21:22:43 +00001655/*
1656 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1657 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001658int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001659{
1660 int ret;
1661 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1662
1663 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001664 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001665
Paul Bakker6c591fa2011-05-05 11:49:20 +00001666 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1667 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1668 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001669
1670 MPI_CHK( mpi_gcd( &G, A, N ) );
1671
1672 if( mpi_cmp_int( &G, 1 ) != 0 )
1673 {
Paul Bakker40e46942009-01-03 21:51:57 +00001674 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001675 goto cleanup;
1676 }
1677
1678 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1679 MPI_CHK( mpi_copy( &TU, &TA ) );
1680 MPI_CHK( mpi_copy( &TB, N ) );
1681 MPI_CHK( mpi_copy( &TV, N ) );
1682
1683 MPI_CHK( mpi_lset( &U1, 1 ) );
1684 MPI_CHK( mpi_lset( &U2, 0 ) );
1685 MPI_CHK( mpi_lset( &V1, 0 ) );
1686 MPI_CHK( mpi_lset( &V2, 1 ) );
1687
1688 do
1689 {
1690 while( ( TU.p[0] & 1 ) == 0 )
1691 {
1692 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1693
1694 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1695 {
1696 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1697 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1698 }
1699
1700 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1701 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1702 }
1703
1704 while( ( TV.p[0] & 1 ) == 0 )
1705 {
1706 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1707
1708 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1709 {
1710 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1711 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1712 }
1713
1714 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1715 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1716 }
1717
1718 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1719 {
1720 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1721 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1722 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1723 }
1724 else
1725 {
1726 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1727 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1728 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1729 }
1730 }
1731 while( mpi_cmp_int( &TU, 0 ) != 0 );
1732
1733 while( mpi_cmp_int( &V1, 0 ) < 0 )
1734 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1735
1736 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1737 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1738
1739 MPI_CHK( mpi_copy( X, &V1 ) );
1740
1741cleanup:
1742
Paul Bakker6c591fa2011-05-05 11:49:20 +00001743 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1744 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1745 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001746
1747 return( ret );
1748}
1749
1750static const int small_prime[] =
1751{
1752 3, 5, 7, 11, 13, 17, 19, 23,
1753 29, 31, 37, 41, 43, 47, 53, 59,
1754 61, 67, 71, 73, 79, 83, 89, 97,
1755 101, 103, 107, 109, 113, 127, 131, 137,
1756 139, 149, 151, 157, 163, 167, 173, 179,
1757 181, 191, 193, 197, 199, 211, 223, 227,
1758 229, 233, 239, 241, 251, 257, 263, 269,
1759 271, 277, 281, 283, 293, 307, 311, 313,
1760 317, 331, 337, 347, 349, 353, 359, 367,
1761 373, 379, 383, 389, 397, 401, 409, 419,
1762 421, 431, 433, 439, 443, 449, 457, 461,
1763 463, 467, 479, 487, 491, 499, 503, 509,
1764 521, 523, 541, 547, 557, 563, 569, 571,
1765 577, 587, 593, 599, 601, 607, 613, 617,
1766 619, 631, 641, 643, 647, 653, 659, 661,
1767 673, 677, 683, 691, 701, 709, 719, 727,
1768 733, 739, 743, 751, 757, 761, 769, 773,
1769 787, 797, 809, 811, 821, 823, 827, 829,
1770 839, 853, 857, 859, 863, 877, 881, 883,
1771 887, 907, 911, 919, 929, 937, 941, 947,
1772 953, 967, 971, 977, 983, 991, 997, -103
1773};
1774
1775/*
1776 * Miller-Rabin primality test (HAC 4.24)
1777 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001778int mpi_is_prime( mpi *X,
1779 int (*f_rng)(void *, unsigned char *, size_t),
1780 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001781{
Paul Bakker23986e52011-04-24 08:57:21 +00001782 int ret, xs;
1783 size_t i, j, n, s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001784 mpi W, R, T, A, RR;
Paul Bakker5121ce52009-01-03 21:22:43 +00001785
Paul Bakker48eab262009-06-25 21:25:49 +00001786 if( mpi_cmp_int( X, 0 ) == 0 ||
1787 mpi_cmp_int( X, 1 ) == 0 )
1788 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1789
1790 if( mpi_cmp_int( X, 2 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001791 return( 0 );
1792
Paul Bakker6c591fa2011-05-05 11:49:20 +00001793 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
1794 mpi_init( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001795
1796 xs = X->s; X->s = 1;
1797
1798 /*
1799 * test trivial factors first
1800 */
1801 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001802 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001803
1804 for( i = 0; small_prime[i] > 0; i++ )
1805 {
Paul Bakkera755ca12011-04-24 09:11:17 +00001806 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001807
1808 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
1809 return( 0 );
1810
1811 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1812
1813 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001814 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001815 }
1816
1817 /*
1818 * W = |X| - 1
1819 * R = W >> lsb( W )
1820 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001821 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001822 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001823 MPI_CHK( mpi_copy( &R, &W ) );
1824 MPI_CHK( mpi_shift_r( &R, s ) );
1825
1826 i = mpi_msb( X );
1827 /*
1828 * HAC, table 4.4
1829 */
1830 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1831 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1832 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1833
1834 for( i = 0; i < n; i++ )
1835 {
1836 /*
1837 * pick a random A, 1 < A < |X| - 1
1838 */
Paul Bakker901c6562012-04-20 13:25:38 +00001839 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001840
Paul Bakkerb94081b2011-01-05 15:53:06 +00001841 if( mpi_cmp_mpi( &A, &W ) >= 0 )
1842 {
1843 j = mpi_msb( &A ) - mpi_msb( &W );
1844 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1845 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001846 A.p[0] |= 3;
1847
1848 /*
1849 * A = A^R mod |X|
1850 */
1851 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1852
1853 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1854 mpi_cmp_int( &A, 1 ) == 0 )
1855 continue;
1856
1857 j = 1;
1858 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1859 {
1860 /*
1861 * A = A * A mod |X|
1862 */
1863 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1864 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1865
1866 if( mpi_cmp_int( &A, 1 ) == 0 )
1867 break;
1868
1869 j++;
1870 }
1871
1872 /*
1873 * not prime if A != |X| - 1 or A == 1
1874 */
1875 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1876 mpi_cmp_int( &A, 1 ) == 0 )
1877 {
Paul Bakker40e46942009-01-03 21:51:57 +00001878 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001879 break;
1880 }
1881 }
1882
1883cleanup:
1884
1885 X->s = xs;
1886
Paul Bakker6c591fa2011-05-05 11:49:20 +00001887 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
1888 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001889
1890 return( ret );
1891}
1892
1893/*
1894 * Prime number generation
1895 */
Paul Bakker23986e52011-04-24 08:57:21 +00001896int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001897 int (*f_rng)(void *, unsigned char *, size_t),
1898 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001899{
Paul Bakker23986e52011-04-24 08:57:21 +00001900 int ret;
1901 size_t k, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001902 mpi Y;
1903
Paul Bakkerfe3256e2011-11-25 12:11:43 +00001904 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00001905 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001906
Paul Bakker6c591fa2011-05-05 11:49:20 +00001907 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001908
1909 n = BITS_TO_LIMBS( nbits );
1910
Paul Bakker901c6562012-04-20 13:25:38 +00001911 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001912
1913 k = mpi_msb( X );
1914 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
1915 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
1916
1917 X->p[0] |= 3;
1918
1919 if( dh_flag == 0 )
1920 {
1921 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
1922 {
Paul Bakker40e46942009-01-03 21:51:57 +00001923 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001924 goto cleanup;
1925
1926 MPI_CHK( mpi_add_int( X, X, 2 ) );
1927 }
1928 }
1929 else
1930 {
1931 MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
1932 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1933
1934 while( 1 )
1935 {
1936 if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
1937 {
1938 if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
1939 break;
1940
Paul Bakker40e46942009-01-03 21:51:57 +00001941 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001942 goto cleanup;
1943 }
1944
Paul Bakker40e46942009-01-03 21:51:57 +00001945 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001946 goto cleanup;
1947
1948 MPI_CHK( mpi_add_int( &Y, X, 1 ) );
1949 MPI_CHK( mpi_add_int( X, X, 2 ) );
1950 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1951 }
1952 }
1953
1954cleanup:
1955
Paul Bakker6c591fa2011-05-05 11:49:20 +00001956 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001957
1958 return( ret );
1959}
1960
1961#endif
1962
Paul Bakker40e46942009-01-03 21:51:57 +00001963#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00001964
Paul Bakker23986e52011-04-24 08:57:21 +00001965#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001966
1967static const int gcd_pairs[GCD_PAIR_COUNT][3] =
1968{
1969 { 693, 609, 21 },
1970 { 1764, 868, 28 },
1971 { 768454923, 542167814, 1 }
1972};
1973
Paul Bakker5121ce52009-01-03 21:22:43 +00001974/*
1975 * Checkup routine
1976 */
1977int mpi_self_test( int verbose )
1978{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001979 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001980 mpi A, E, N, X, Y, U, V;
1981
Paul Bakker6c591fa2011-05-05 11:49:20 +00001982 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
1983 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00001984
1985 MPI_CHK( mpi_read_string( &A, 16,
1986 "EFE021C2645FD1DC586E69184AF4A31E" \
1987 "D5F53E93B5F123FA41680867BA110131" \
1988 "944FE7952E2517337780CB0DB80E61AA" \
1989 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
1990
1991 MPI_CHK( mpi_read_string( &E, 16,
1992 "B2E7EFD37075B9F03FF989C7C5051C20" \
1993 "34D2A323810251127E7BF8625A4F49A5" \
1994 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
1995 "5B5C25763222FEFCCFC38B832366C29E" ) );
1996
1997 MPI_CHK( mpi_read_string( &N, 16,
1998 "0066A198186C18C10B2F5ED9B522752A" \
1999 "9830B69916E535C8F047518A889A43A5" \
2000 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2001
2002 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2003
2004 MPI_CHK( mpi_read_string( &U, 16,
2005 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2006 "9E857EA95A03512E2BAE7391688D264A" \
2007 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2008 "8001B72E848A38CAE1C65F78E56ABDEF" \
2009 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2010 "ECF677152EF804370C1A305CAF3B5BF1" \
2011 "30879B56C61DE584A0F53A2447A51E" ) );
2012
2013 if( verbose != 0 )
2014 printf( " MPI test #1 (mul_mpi): " );
2015
2016 if( mpi_cmp_mpi( &X, &U ) != 0 )
2017 {
2018 if( verbose != 0 )
2019 printf( "failed\n" );
2020
2021 return( 1 );
2022 }
2023
2024 if( verbose != 0 )
2025 printf( "passed\n" );
2026
2027 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2028
2029 MPI_CHK( mpi_read_string( &U, 16,
2030 "256567336059E52CAE22925474705F39A94" ) );
2031
2032 MPI_CHK( mpi_read_string( &V, 16,
2033 "6613F26162223DF488E9CD48CC132C7A" \
2034 "0AC93C701B001B092E4E5B9F73BCD27B" \
2035 "9EE50D0657C77F374E903CDFA4C642" ) );
2036
2037 if( verbose != 0 )
2038 printf( " MPI test #2 (div_mpi): " );
2039
2040 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2041 mpi_cmp_mpi( &Y, &V ) != 0 )
2042 {
2043 if( verbose != 0 )
2044 printf( "failed\n" );
2045
2046 return( 1 );
2047 }
2048
2049 if( verbose != 0 )
2050 printf( "passed\n" );
2051
2052 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2053
2054 MPI_CHK( mpi_read_string( &U, 16,
2055 "36E139AEA55215609D2816998ED020BB" \
2056 "BD96C37890F65171D948E9BC7CBAA4D9" \
2057 "325D24D6A3C12710F10A09FA08AB87" ) );
2058
2059 if( verbose != 0 )
2060 printf( " MPI test #3 (exp_mod): " );
2061
2062 if( mpi_cmp_mpi( &X, &U ) != 0 )
2063 {
2064 if( verbose != 0 )
2065 printf( "failed\n" );
2066
2067 return( 1 );
2068 }
2069
2070 if( verbose != 0 )
2071 printf( "passed\n" );
2072
Paul Bakker5690efc2011-05-26 13:16:06 +00002073#if defined(POLARSSL_GENPRIME)
Paul Bakker5121ce52009-01-03 21:22:43 +00002074 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2075
2076 MPI_CHK( mpi_read_string( &U, 16,
2077 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2078 "C3DBA76456363A10869622EAC2DD84EC" \
2079 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2080
2081 if( verbose != 0 )
2082 printf( " MPI test #4 (inv_mod): " );
2083
2084 if( mpi_cmp_mpi( &X, &U ) != 0 )
2085 {
2086 if( verbose != 0 )
2087 printf( "failed\n" );
2088
2089 return( 1 );
2090 }
2091
2092 if( verbose != 0 )
2093 printf( "passed\n" );
Paul Bakker5690efc2011-05-26 13:16:06 +00002094#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002095
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002096 if( verbose != 0 )
2097 printf( " MPI test #5 (simple gcd): " );
2098
2099 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2100 {
2101 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002102 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002103
Paul Bakker23986e52011-04-24 08:57:21 +00002104 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002105
Paul Bakker23986e52011-04-24 08:57:21 +00002106 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2107 {
2108 if( verbose != 0 )
2109 printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002110
Paul Bakker23986e52011-04-24 08:57:21 +00002111 return( 1 );
2112 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002113 }
2114
2115 if( verbose != 0 )
2116 printf( "passed\n" );
2117
Paul Bakker5121ce52009-01-03 21:22:43 +00002118cleanup:
2119
2120 if( ret != 0 && verbose != 0 )
2121 printf( "Unexpected error, return code = %08X\n", ret );
2122
Paul Bakker6c591fa2011-05-05 11:49:20 +00002123 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2124 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002125
2126 if( verbose != 0 )
2127 printf( "\n" );
2128
2129 return( ret );
2130}
2131
2132#endif
2133
2134#endif