blob: f2a49ecac3e16544c0f4df42ed2e17147ce34505 [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
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000409 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000410 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000411 k = 1;
412 }
413 }
414 }
415 else
416 {
417 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000418
419 if( T.s == -1 )
420 T.s = 1;
421
Paul Bakker5121ce52009-01-03 21:22:43 +0000422 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
423 }
424
425 *p++ = '\0';
426 *slen = p - s;
427
428cleanup:
429
Paul Bakker6c591fa2011-05-05 11:49:20 +0000430 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000431
432 return( ret );
433}
434
Paul Bakker335db3f2011-04-25 15:28:35 +0000435#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000436/*
437 * Read X from an opened file
438 */
439int mpi_read_file( mpi *X, int radix, FILE *fin )
440{
Paul Bakkera755ca12011-04-24 09:11:17 +0000441 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000442 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000443 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000444 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000445 * Buffer should have space for (short) label and decimal formatted MPI,
446 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000447 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000448 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000449
450 memset( s, 0, sizeof( s ) );
451 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000452 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000453
454 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000455 if( slen == sizeof( s ) - 2 )
456 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
457
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
459 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
460
461 p = s + slen;
462 while( --p >= s )
463 if( mpi_get_digit( &d, radix, *p ) != 0 )
464 break;
465
466 return( mpi_read_string( X, radix, p + 1 ) );
467}
468
469/*
470 * Write X into an opened file (or stdout if fout == NULL)
471 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000472int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000473{
Paul Bakker23986e52011-04-24 08:57:21 +0000474 int ret;
475 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000476 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000477 * Buffer should have space for (short) label and decimal formatted MPI,
478 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000479 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000480 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000481
482 n = sizeof( s );
483 memset( s, 0, n );
484 n -= 2;
485
Paul Bakker23986e52011-04-24 08:57:21 +0000486 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000487
488 if( p == NULL ) p = "";
489
490 plen = strlen( p );
491 slen = strlen( s );
492 s[slen++] = '\r';
493 s[slen++] = '\n';
494
495 if( fout != NULL )
496 {
497 if( fwrite( p, 1, plen, fout ) != plen ||
498 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000499 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000500 }
501 else
502 printf( "%s%s", p, s );
503
504cleanup:
505
506 return( ret );
507}
Paul Bakker335db3f2011-04-25 15:28:35 +0000508#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000509
510/*
511 * Import X from unsigned binary data, big endian
512 */
Paul Bakker23986e52011-04-24 08:57:21 +0000513int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000514{
Paul Bakker23986e52011-04-24 08:57:21 +0000515 int ret;
516 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000517
518 for( n = 0; n < buflen; n++ )
519 if( buf[n] != 0 )
520 break;
521
522 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
523 MPI_CHK( mpi_lset( X, 0 ) );
524
Paul Bakker23986e52011-04-24 08:57:21 +0000525 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000526 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000527
528cleanup:
529
530 return( ret );
531}
532
533/*
534 * Export X into unsigned binary data, big endian
535 */
Paul Bakker23986e52011-04-24 08:57:21 +0000536int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000537{
Paul Bakker23986e52011-04-24 08:57:21 +0000538 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
540 n = mpi_size( X );
541
542 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000543 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000544
545 memset( buf, 0, buflen );
546
547 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
548 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
549
550 return( 0 );
551}
552
553/*
554 * Left-shift: X <<= count
555 */
Paul Bakker23986e52011-04-24 08:57:21 +0000556int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000557{
Paul Bakker23986e52011-04-24 08:57:21 +0000558 int ret;
559 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000560 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000561
562 v0 = count / (biL );
563 t1 = count & (biL - 1);
564
565 i = mpi_msb( X ) + count;
566
Paul Bakkerf9688572011-05-05 10:00:45 +0000567 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000568 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
569
570 ret = 0;
571
572 /*
573 * shift by count / limb_size
574 */
575 if( v0 > 0 )
576 {
Paul Bakker23986e52011-04-24 08:57:21 +0000577 for( i = X->n; i > v0; i-- )
578 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000579
Paul Bakker23986e52011-04-24 08:57:21 +0000580 for( ; i > 0; i-- )
581 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000582 }
583
584 /*
585 * shift by count % limb_size
586 */
587 if( t1 > 0 )
588 {
589 for( i = v0; i < X->n; i++ )
590 {
591 r1 = X->p[i] >> (biL - t1);
592 X->p[i] <<= t1;
593 X->p[i] |= r0;
594 r0 = r1;
595 }
596 }
597
598cleanup:
599
600 return( ret );
601}
602
603/*
604 * Right-shift: X >>= count
605 */
Paul Bakker23986e52011-04-24 08:57:21 +0000606int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000607{
Paul Bakker23986e52011-04-24 08:57:21 +0000608 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000609 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000610
611 v0 = count / biL;
612 v1 = count & (biL - 1);
613
614 /*
615 * shift by count / limb_size
616 */
617 if( v0 > 0 )
618 {
619 for( i = 0; i < X->n - v0; i++ )
620 X->p[i] = X->p[i + v0];
621
622 for( ; i < X->n; i++ )
623 X->p[i] = 0;
624 }
625
626 /*
627 * shift by count % limb_size
628 */
629 if( v1 > 0 )
630 {
Paul Bakker23986e52011-04-24 08:57:21 +0000631 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000632 {
Paul Bakker23986e52011-04-24 08:57:21 +0000633 r1 = X->p[i - 1] << (biL - v1);
634 X->p[i - 1] >>= v1;
635 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000636 r0 = r1;
637 }
638 }
639
640 return( 0 );
641}
642
643/*
644 * Compare unsigned values
645 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000646int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000647{
Paul Bakker23986e52011-04-24 08:57:21 +0000648 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000649
Paul Bakker23986e52011-04-24 08:57:21 +0000650 for( i = X->n; i > 0; i-- )
651 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000652 break;
653
Paul Bakker23986e52011-04-24 08:57:21 +0000654 for( j = Y->n; j > 0; j-- )
655 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000656 break;
657
Paul Bakker23986e52011-04-24 08:57:21 +0000658 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000659 return( 0 );
660
661 if( i > j ) return( 1 );
662 if( j > i ) return( -1 );
663
Paul Bakker23986e52011-04-24 08:57:21 +0000664 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000665 {
Paul Bakker23986e52011-04-24 08:57:21 +0000666 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
667 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000668 }
669
670 return( 0 );
671}
672
673/*
674 * Compare signed values
675 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000676int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000677{
Paul Bakker23986e52011-04-24 08:57:21 +0000678 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000679
Paul Bakker23986e52011-04-24 08:57:21 +0000680 for( i = X->n; i > 0; i-- )
681 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000682 break;
683
Paul Bakker23986e52011-04-24 08:57:21 +0000684 for( j = Y->n; j > 0; j-- )
685 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000686 break;
687
Paul Bakker23986e52011-04-24 08:57:21 +0000688 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000689 return( 0 );
690
691 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000692 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000693
694 if( X->s > 0 && Y->s < 0 ) return( 1 );
695 if( Y->s > 0 && X->s < 0 ) return( -1 );
696
Paul Bakker23986e52011-04-24 08:57:21 +0000697 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000698 {
Paul Bakker23986e52011-04-24 08:57:21 +0000699 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
700 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000701 }
702
703 return( 0 );
704}
705
706/*
707 * Compare signed values
708 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000709int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000710{
711 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000712 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000713
714 *p = ( z < 0 ) ? -z : z;
715 Y.s = ( z < 0 ) ? -1 : 1;
716 Y.n = 1;
717 Y.p = p;
718
719 return( mpi_cmp_mpi( X, &Y ) );
720}
721
722/*
723 * Unsigned addition: X = |A| + |B| (HAC 14.7)
724 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000725int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000726{
Paul Bakker23986e52011-04-24 08:57:21 +0000727 int ret;
728 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000729 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000730
731 if( X == B )
732 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000733 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000734 }
735
736 if( X != A )
737 MPI_CHK( mpi_copy( X, A ) );
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000738
739 /*
740 * X should always be positive as a result of unsigned additions.
741 */
742 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000743
Paul Bakker23986e52011-04-24 08:57:21 +0000744 for( j = B->n; j > 0; j-- )
745 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000746 break;
747
Paul Bakker23986e52011-04-24 08:57:21 +0000748 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000749
750 o = B->p; p = X->p; c = 0;
751
Paul Bakker23986e52011-04-24 08:57:21 +0000752 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000753 {
754 *p += c; c = ( *p < c );
755 *p += *o; c += ( *p < *o );
756 }
757
758 while( c != 0 )
759 {
760 if( i >= X->n )
761 {
762 MPI_CHK( mpi_grow( X, i + 1 ) );
763 p = X->p + i;
764 }
765
Paul Bakker2d319fd2012-09-16 21:34:26 +0000766 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000767 }
768
769cleanup:
770
771 return( ret );
772}
773
774/*
775 * Helper for mpi substraction
776 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000777static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000778{
Paul Bakker23986e52011-04-24 08:57:21 +0000779 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000780 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000781
782 for( i = c = 0; i < n; i++, s++, d++ )
783 {
784 z = ( *d < c ); *d -= c;
785 c = ( *d < *s ) + z; *d -= *s;
786 }
787
788 while( c != 0 )
789 {
790 z = ( *d < c ); *d -= c;
791 c = z; i++; d++;
792 }
793}
794
795/*
796 * Unsigned substraction: X = |A| - |B| (HAC 14.9)
797 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000798int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000799{
800 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000801 int ret;
802 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000803
804 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000805 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000806
Paul Bakker6c591fa2011-05-05 11:49:20 +0000807 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000808
809 if( X == B )
810 {
811 MPI_CHK( mpi_copy( &TB, B ) );
812 B = &TB;
813 }
814
815 if( X != A )
816 MPI_CHK( mpi_copy( X, A ) );
817
Paul Bakker1ef7a532009-06-20 10:50:55 +0000818 /*
819 * X should always be positive as a result of unsigned substractions.
820 */
821 X->s = 1;
822
Paul Bakker5121ce52009-01-03 21:22:43 +0000823 ret = 0;
824
Paul Bakker23986e52011-04-24 08:57:21 +0000825 for( n = B->n; n > 0; n-- )
826 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000827 break;
828
Paul Bakker23986e52011-04-24 08:57:21 +0000829 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000830
831cleanup:
832
Paul Bakker6c591fa2011-05-05 11:49:20 +0000833 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000834
835 return( ret );
836}
837
838/*
839 * Signed addition: X = A + B
840 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000841int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000842{
843 int ret, s = A->s;
844
845 if( A->s * B->s < 0 )
846 {
847 if( mpi_cmp_abs( A, B ) >= 0 )
848 {
849 MPI_CHK( mpi_sub_abs( X, A, B ) );
850 X->s = s;
851 }
852 else
853 {
854 MPI_CHK( mpi_sub_abs( X, B, A ) );
855 X->s = -s;
856 }
857 }
858 else
859 {
860 MPI_CHK( mpi_add_abs( X, A, B ) );
861 X->s = s;
862 }
863
864cleanup:
865
866 return( ret );
867}
868
869/*
870 * Signed substraction: X = A - B
871 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000872int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000873{
874 int ret, s = A->s;
875
876 if( A->s * B->s > 0 )
877 {
878 if( mpi_cmp_abs( A, B ) >= 0 )
879 {
880 MPI_CHK( mpi_sub_abs( X, A, B ) );
881 X->s = s;
882 }
883 else
884 {
885 MPI_CHK( mpi_sub_abs( X, B, A ) );
886 X->s = -s;
887 }
888 }
889 else
890 {
891 MPI_CHK( mpi_add_abs( X, A, B ) );
892 X->s = s;
893 }
894
895cleanup:
896
897 return( ret );
898}
899
900/*
901 * Signed addition: X = A + b
902 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000903int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000904{
905 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000906 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000907
908 p[0] = ( b < 0 ) ? -b : b;
909 _B.s = ( b < 0 ) ? -1 : 1;
910 _B.n = 1;
911 _B.p = p;
912
913 return( mpi_add_mpi( X, A, &_B ) );
914}
915
916/*
917 * Signed substraction: X = A - b
918 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000919int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000920{
921 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000922 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000923
924 p[0] = ( b < 0 ) ? -b : b;
925 _B.s = ( b < 0 ) ? -1 : 1;
926 _B.n = 1;
927 _B.p = p;
928
929 return( mpi_sub_mpi( X, A, &_B ) );
930}
931
932/*
933 * Helper for mpi multiplication
934 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000935static void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000936{
Paul Bakkera755ca12011-04-24 09:11:17 +0000937 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000938
939#if defined(MULADDC_HUIT)
940 for( ; i >= 8; i -= 8 )
941 {
942 MULADDC_INIT
943 MULADDC_HUIT
944 MULADDC_STOP
945 }
946
947 for( ; i > 0; i-- )
948 {
949 MULADDC_INIT
950 MULADDC_CORE
951 MULADDC_STOP
952 }
953#else
954 for( ; i >= 16; i -= 16 )
955 {
956 MULADDC_INIT
957 MULADDC_CORE MULADDC_CORE
958 MULADDC_CORE MULADDC_CORE
959 MULADDC_CORE MULADDC_CORE
960 MULADDC_CORE MULADDC_CORE
961
962 MULADDC_CORE MULADDC_CORE
963 MULADDC_CORE MULADDC_CORE
964 MULADDC_CORE MULADDC_CORE
965 MULADDC_CORE MULADDC_CORE
966 MULADDC_STOP
967 }
968
969 for( ; i >= 8; i -= 8 )
970 {
971 MULADDC_INIT
972 MULADDC_CORE MULADDC_CORE
973 MULADDC_CORE MULADDC_CORE
974
975 MULADDC_CORE MULADDC_CORE
976 MULADDC_CORE MULADDC_CORE
977 MULADDC_STOP
978 }
979
980 for( ; i > 0; i-- )
981 {
982 MULADDC_INIT
983 MULADDC_CORE
984 MULADDC_STOP
985 }
986#endif
987
988 t++;
989
990 do {
991 *d += c; c = ( *d < c ); d++;
992 }
993 while( c != 0 );
994}
995
996/*
997 * Baseline multiplication: X = A * B (HAC 14.12)
998 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000999int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001000{
Paul Bakker23986e52011-04-24 08:57:21 +00001001 int ret;
1002 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001003 mpi TA, TB;
1004
Paul Bakker6c591fa2011-05-05 11:49:20 +00001005 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001006
1007 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1008 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1009
Paul Bakker23986e52011-04-24 08:57:21 +00001010 for( i = A->n; i > 0; i-- )
1011 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001012 break;
1013
Paul Bakker23986e52011-04-24 08:57:21 +00001014 for( j = B->n; j > 0; j-- )
1015 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001016 break;
1017
Paul Bakker23986e52011-04-24 08:57:21 +00001018 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001019 MPI_CHK( mpi_lset( X, 0 ) );
1020
Paul Bakker23986e52011-04-24 08:57:21 +00001021 for( i++; j > 0; j-- )
1022 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001023
1024 X->s = A->s * B->s;
1025
1026cleanup:
1027
Paul Bakker6c591fa2011-05-05 11:49:20 +00001028 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001029
1030 return( ret );
1031}
1032
1033/*
1034 * Baseline multiplication: X = A * b
1035 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001036int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001037{
1038 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001039 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001040
1041 _B.s = 1;
1042 _B.n = 1;
1043 _B.p = p;
1044 p[0] = b;
1045
1046 return( mpi_mul_mpi( X, A, &_B ) );
1047}
1048
1049/*
1050 * Division by mpi: A = Q * B + R (HAC 14.20)
1051 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001052int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001053{
Paul Bakker23986e52011-04-24 08:57:21 +00001054 int ret;
1055 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001056 mpi X, Y, Z, T1, T2;
1057
1058 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001059 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001060
Paul Bakker6c591fa2011-05-05 11:49:20 +00001061 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1062 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001063
1064 if( mpi_cmp_abs( A, B ) < 0 )
1065 {
1066 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1067 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1068 return( 0 );
1069 }
1070
1071 MPI_CHK( mpi_copy( &X, A ) );
1072 MPI_CHK( mpi_copy( &Y, B ) );
1073 X.s = Y.s = 1;
1074
1075 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1076 MPI_CHK( mpi_lset( &Z, 0 ) );
1077 MPI_CHK( mpi_grow( &T1, 2 ) );
1078 MPI_CHK( mpi_grow( &T2, 3 ) );
1079
1080 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001081 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001082 {
1083 k = biL - 1 - k;
1084 MPI_CHK( mpi_shift_l( &X, k ) );
1085 MPI_CHK( mpi_shift_l( &Y, k ) );
1086 }
1087 else k = 0;
1088
1089 n = X.n - 1;
1090 t = Y.n - 1;
Paul Bakkerc110d022012-10-19 12:15:08 +00001091 MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001092
1093 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1094 {
1095 Z.p[n - t]++;
1096 mpi_sub_mpi( &X, &X, &Y );
1097 }
1098 mpi_shift_r( &Y, biL * (n - t) );
1099
1100 for( i = n; i > t ; i-- )
1101 {
1102 if( X.p[i] >= Y.p[t] )
1103 Z.p[i - t - 1] = ~0;
1104 else
1105 {
Paul Bakker62261d62012-10-02 12:19:31 +00001106#if defined(POLARSSL_HAVE_UDBL)
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001107 t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001108
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001109 r = (t_udbl) X.p[i] << biL;
1110 r |= (t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001111 r /= Y.p[t];
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001112 if( r > ((t_udbl) 1 << biL) - 1)
1113 r = ((t_udbl) 1 << biL) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001114
Paul Bakkera755ca12011-04-24 09:11:17 +00001115 Z.p[i - t - 1] = (t_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001116#else
1117 /*
1118 * __udiv_qrnnd_c, from gmp/longlong.h
1119 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001120 t_uint q0, q1, r0, r1;
1121 t_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001122
1123 d = Y.p[t];
1124 d0 = ( d << biH ) >> biH;
1125 d1 = ( d >> biH );
1126
1127 q1 = X.p[i] / d1;
1128 r1 = X.p[i] - d1 * q1;
1129 r1 <<= biH;
1130 r1 |= ( X.p[i - 1] >> biH );
1131
1132 m = q1 * d0;
1133 if( r1 < m )
1134 {
1135 q1--, r1 += d;
1136 while( r1 >= d && r1 < m )
1137 q1--, r1 += d;
1138 }
1139 r1 -= m;
1140
1141 q0 = r1 / d1;
1142 r0 = r1 - d1 * q0;
1143 r0 <<= biH;
1144 r0 |= ( X.p[i - 1] << biH ) >> biH;
1145
1146 m = q0 * d0;
1147 if( r0 < m )
1148 {
1149 q0--, r0 += d;
1150 while( r0 >= d && r0 < m )
1151 q0--, r0 += d;
1152 }
1153 r0 -= m;
1154
1155 Z.p[i - t - 1] = ( q1 << biH ) | q0;
1156#endif
1157 }
1158
1159 Z.p[i - t - 1]++;
1160 do
1161 {
1162 Z.p[i - t - 1]--;
1163
1164 MPI_CHK( mpi_lset( &T1, 0 ) );
1165 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1166 T1.p[1] = Y.p[t];
1167 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1168
1169 MPI_CHK( mpi_lset( &T2, 0 ) );
1170 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1171 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1172 T2.p[2] = X.p[i];
1173 }
1174 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1175
1176 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1177 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1178 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1179
1180 if( mpi_cmp_int( &X, 0 ) < 0 )
1181 {
1182 MPI_CHK( mpi_copy( &T1, &Y ) );
1183 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1184 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1185 Z.p[i - t - 1]--;
1186 }
1187 }
1188
1189 if( Q != NULL )
1190 {
1191 mpi_copy( Q, &Z );
1192 Q->s = A->s * B->s;
1193 }
1194
1195 if( R != NULL )
1196 {
1197 mpi_shift_r( &X, k );
1198 mpi_copy( R, &X );
1199
1200 R->s = A->s;
1201 if( mpi_cmp_int( R, 0 ) == 0 )
1202 R->s = 1;
1203 }
1204
1205cleanup:
1206
Paul Bakker6c591fa2011-05-05 11:49:20 +00001207 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1208 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001209
1210 return( ret );
1211}
1212
1213/*
1214 * Division by int: A = Q * b + R
1215 *
1216 * Returns 0 if successful
1217 * 1 if memory allocation failed
Paul Bakker40e46942009-01-03 21:51:57 +00001218 * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
Paul Bakker5121ce52009-01-03 21:22:43 +00001219 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001220int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001221{
1222 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001223 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001224
1225 p[0] = ( b < 0 ) ? -b : b;
1226 _B.s = ( b < 0 ) ? -1 : 1;
1227 _B.n = 1;
1228 _B.p = p;
1229
1230 return( mpi_div_mpi( Q, R, A, &_B ) );
1231}
1232
1233/*
1234 * Modulo: R = A mod B
1235 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001236int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001237{
1238 int ret;
1239
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001240 if( mpi_cmp_int( B, 0 ) < 0 )
1241 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1242
Paul Bakker5121ce52009-01-03 21:22:43 +00001243 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1244
1245 while( mpi_cmp_int( R, 0 ) < 0 )
1246 MPI_CHK( mpi_add_mpi( R, R, B ) );
1247
1248 while( mpi_cmp_mpi( R, B ) >= 0 )
1249 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1250
1251cleanup:
1252
1253 return( ret );
1254}
1255
1256/*
1257 * Modulo: r = A mod b
1258 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001259int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001260{
Paul Bakker23986e52011-04-24 08:57:21 +00001261 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001262 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001263
1264 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001265 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001266
1267 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001268 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001269
1270 /*
1271 * handle trivial cases
1272 */
1273 if( b == 1 )
1274 {
1275 *r = 0;
1276 return( 0 );
1277 }
1278
1279 if( b == 2 )
1280 {
1281 *r = A->p[0] & 1;
1282 return( 0 );
1283 }
1284
1285 /*
1286 * general case
1287 */
Paul Bakker23986e52011-04-24 08:57:21 +00001288 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001289 {
Paul Bakker23986e52011-04-24 08:57:21 +00001290 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001291 y = ( y << biH ) | ( x >> biH );
1292 z = y / b;
1293 y -= z * b;
1294
1295 x <<= biH;
1296 y = ( y << biH ) | ( x >> biH );
1297 z = y / b;
1298 y -= z * b;
1299 }
1300
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001301 /*
1302 * If A is negative, then the current y represents a negative value.
1303 * Flipping it to the positive side.
1304 */
1305 if( A->s < 0 && y != 0 )
1306 y = b - y;
1307
Paul Bakker5121ce52009-01-03 21:22:43 +00001308 *r = y;
1309
1310 return( 0 );
1311}
1312
1313/*
1314 * Fast Montgomery initialization (thanks to Tom St Denis)
1315 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001316static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001317{
Paul Bakkera755ca12011-04-24 09:11:17 +00001318 t_uint x, m0 = N->p[0];
Paul Bakker5121ce52009-01-03 21:22:43 +00001319
1320 x = m0;
1321 x += ( ( m0 + 2 ) & 4 ) << 1;
1322 x *= ( 2 - ( m0 * x ) );
1323
1324 if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
1325 if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
1326 if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
1327
1328 *mm = ~x + 1;
1329}
1330
1331/*
1332 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1333 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001334static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001335{
Paul Bakker23986e52011-04-24 08:57:21 +00001336 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001337 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001338
1339 memset( T->p, 0, T->n * ciL );
1340
1341 d = T->p;
1342 n = N->n;
1343 m = ( B->n < n ) ? B->n : n;
1344
1345 for( i = 0; i < n; i++ )
1346 {
1347 /*
1348 * T = (T + u0*B + u1*N) / 2^biL
1349 */
1350 u0 = A->p[i];
1351 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1352
1353 mpi_mul_hlp( m, B->p, d, u0 );
1354 mpi_mul_hlp( n, N->p, d, u1 );
1355
1356 *d++ = u0; d[n + 1] = 0;
1357 }
1358
1359 memcpy( A->p, d, (n + 1) * ciL );
1360
1361 if( mpi_cmp_abs( A, N ) >= 0 )
1362 mpi_sub_hlp( n, N->p, A->p );
1363 else
1364 /* prevent timing attacks */
1365 mpi_sub_hlp( n, A->p, T->p );
1366}
1367
1368/*
1369 * Montgomery reduction: A = A * R^-1 mod N
1370 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001371static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001372{
Paul Bakkera755ca12011-04-24 09:11:17 +00001373 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001374 mpi U;
1375
1376 U.n = U.s = z;
1377 U.p = &z;
1378
1379 mpi_montmul( A, &U, N, mm, T );
1380}
1381
1382/*
1383 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1384 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001385int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001386{
Paul Bakker23986e52011-04-24 08:57:21 +00001387 int ret;
1388 size_t wbits, wsize, one = 1;
1389 size_t i, j, nblimbs;
1390 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001391 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001392 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1393 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001394
1395 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001396 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001397
Paul Bakkerf6198c12012-05-16 08:02:29 +00001398 if( mpi_cmp_int( E, 0 ) < 0 )
1399 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1400
1401 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001402 * Init temps and window size
1403 */
1404 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001405 mpi_init( &RR ); mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001406 memset( W, 0, sizeof( W ) );
1407
1408 i = mpi_msb( E );
1409
1410 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1411 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1412
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001413 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1414 wsize = POLARSSL_MPI_WINDOW_SIZE;
1415
Paul Bakker5121ce52009-01-03 21:22:43 +00001416 j = N->n + 1;
1417 MPI_CHK( mpi_grow( X, j ) );
1418 MPI_CHK( mpi_grow( &W[1], j ) );
1419 MPI_CHK( mpi_grow( &T, j * 2 ) );
1420
1421 /*
Paul Bakker50546922012-05-19 08:40:49 +00001422 * Compensate for negative A (and correct at the end)
1423 */
1424 neg = ( A->s == -1 );
1425
1426 mpi_init( &Apos );
1427 if( neg )
1428 {
1429 MPI_CHK( mpi_copy( &Apos, A ) );
1430 Apos.s = 1;
1431 A = &Apos;
1432 }
1433
1434 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001435 * If 1st call, pre-compute R^2 mod N
1436 */
1437 if( _RR == NULL || _RR->p == NULL )
1438 {
1439 MPI_CHK( mpi_lset( &RR, 1 ) );
1440 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1441 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1442
1443 if( _RR != NULL )
1444 memcpy( _RR, &RR, sizeof( mpi ) );
1445 }
1446 else
1447 memcpy( &RR, _RR, sizeof( mpi ) );
1448
1449 /*
1450 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1451 */
1452 if( mpi_cmp_mpi( A, N ) >= 0 )
1453 mpi_mod_mpi( &W[1], A, N );
1454 else mpi_copy( &W[1], A );
1455
1456 mpi_montmul( &W[1], &RR, N, mm, &T );
1457
1458 /*
1459 * X = R^2 * R^-1 mod N = R mod N
1460 */
1461 MPI_CHK( mpi_copy( X, &RR ) );
1462 mpi_montred( X, N, mm, &T );
1463
1464 if( wsize > 1 )
1465 {
1466 /*
1467 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1468 */
Paul Bakker23986e52011-04-24 08:57:21 +00001469 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001470
1471 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1472 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1473
1474 for( i = 0; i < wsize - 1; i++ )
1475 mpi_montmul( &W[j], &W[j], N, mm, &T );
1476
1477 /*
1478 * W[i] = W[i - 1] * W[1]
1479 */
Paul Bakker23986e52011-04-24 08:57:21 +00001480 for( i = j + 1; i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001481 {
1482 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1483 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1484
1485 mpi_montmul( &W[i], &W[1], N, mm, &T );
1486 }
1487 }
1488
1489 nblimbs = E->n;
1490 bufsize = 0;
1491 nbits = 0;
1492 wbits = 0;
1493 state = 0;
1494
1495 while( 1 )
1496 {
1497 if( bufsize == 0 )
1498 {
1499 if( nblimbs-- == 0 )
1500 break;
1501
Paul Bakkera755ca12011-04-24 09:11:17 +00001502 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001503 }
1504
1505 bufsize--;
1506
1507 ei = (E->p[nblimbs] >> bufsize) & 1;
1508
1509 /*
1510 * skip leading 0s
1511 */
1512 if( ei == 0 && state == 0 )
1513 continue;
1514
1515 if( ei == 0 && state == 1 )
1516 {
1517 /*
1518 * out of window, square X
1519 */
1520 mpi_montmul( X, X, N, mm, &T );
1521 continue;
1522 }
1523
1524 /*
1525 * add ei to current window
1526 */
1527 state = 2;
1528
1529 nbits++;
1530 wbits |= (ei << (wsize - nbits));
1531
1532 if( nbits == wsize )
1533 {
1534 /*
1535 * X = X^wsize R^-1 mod N
1536 */
1537 for( i = 0; i < wsize; i++ )
1538 mpi_montmul( X, X, N, mm, &T );
1539
1540 /*
1541 * X = X * W[wbits] R^-1 mod N
1542 */
1543 mpi_montmul( X, &W[wbits], N, mm, &T );
1544
1545 state--;
1546 nbits = 0;
1547 wbits = 0;
1548 }
1549 }
1550
1551 /*
1552 * process the remaining bits
1553 */
1554 for( i = 0; i < nbits; i++ )
1555 {
1556 mpi_montmul( X, X, N, mm, &T );
1557
1558 wbits <<= 1;
1559
Paul Bakker23986e52011-04-24 08:57:21 +00001560 if( (wbits & (one << wsize)) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001561 mpi_montmul( X, &W[1], N, mm, &T );
1562 }
1563
1564 /*
1565 * X = A^E * R * R^-1 mod N = A^E mod N
1566 */
1567 mpi_montred( X, N, mm, &T );
1568
Paul Bakkerf6198c12012-05-16 08:02:29 +00001569 if( neg )
1570 {
1571 X->s = -1;
1572 mpi_add_mpi( X, N, X );
1573 }
1574
Paul Bakker5121ce52009-01-03 21:22:43 +00001575cleanup:
1576
Paul Bakker23986e52011-04-24 08:57:21 +00001577 for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001578 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001579
Paul Bakkerf6198c12012-05-16 08:02:29 +00001580 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001581
1582 if( _RR == NULL )
1583 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001584
1585 return( ret );
1586}
1587
Paul Bakker5121ce52009-01-03 21:22:43 +00001588/*
1589 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1590 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001591int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001592{
Paul Bakker23986e52011-04-24 08:57:21 +00001593 int ret;
1594 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001595 mpi TG, TA, TB;
1596
Paul Bakker6c591fa2011-05-05 11:49:20 +00001597 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001598
Paul Bakker5121ce52009-01-03 21:22:43 +00001599 MPI_CHK( mpi_copy( &TA, A ) );
1600 MPI_CHK( mpi_copy( &TB, B ) );
1601
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001602 lz = mpi_lsb( &TA );
1603 lzt = mpi_lsb( &TB );
1604
1605 if ( lzt < lz )
1606 lz = lzt;
1607
1608 MPI_CHK( mpi_shift_r( &TA, lz ) );
1609 MPI_CHK( mpi_shift_r( &TB, lz ) );
1610
Paul Bakker5121ce52009-01-03 21:22:43 +00001611 TA.s = TB.s = 1;
1612
1613 while( mpi_cmp_int( &TA, 0 ) != 0 )
1614 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001615 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1616 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001617
1618 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1619 {
1620 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1621 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1622 }
1623 else
1624 {
1625 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1626 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1627 }
1628 }
1629
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001630 MPI_CHK( mpi_shift_l( &TB, lz ) );
1631 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001632
1633cleanup:
1634
Paul Bakker6c591fa2011-05-05 11:49:20 +00001635 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001636
1637 return( ret );
1638}
1639
Paul Bakkera3d195c2011-11-27 21:07:34 +00001640int mpi_fill_random( mpi *X, size_t size,
1641 int (*f_rng)(void *, unsigned char *, size_t),
1642 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001643{
Paul Bakker23986e52011-04-24 08:57:21 +00001644 int ret;
Paul Bakker287781a2011-03-26 13:18:49 +00001645
Paul Bakker39dfdac2012-02-12 17:17:27 +00001646 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001647 MPI_CHK( mpi_lset( X, 0 ) );
1648
Paul Bakker39dfdac2012-02-12 17:17:27 +00001649 MPI_CHK( f_rng( p_rng, (unsigned char *) X->p, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001650
1651cleanup:
1652 return( ret );
1653}
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
Paul Bakkerd9374b02012-11-02 11:02:58 +00001750#if defined(POLARSSL_GENPRIME)
1751
Paul Bakker5121ce52009-01-03 21:22:43 +00001752static const int small_prime[] =
1753{
1754 3, 5, 7, 11, 13, 17, 19, 23,
1755 29, 31, 37, 41, 43, 47, 53, 59,
1756 61, 67, 71, 73, 79, 83, 89, 97,
1757 101, 103, 107, 109, 113, 127, 131, 137,
1758 139, 149, 151, 157, 163, 167, 173, 179,
1759 181, 191, 193, 197, 199, 211, 223, 227,
1760 229, 233, 239, 241, 251, 257, 263, 269,
1761 271, 277, 281, 283, 293, 307, 311, 313,
1762 317, 331, 337, 347, 349, 353, 359, 367,
1763 373, 379, 383, 389, 397, 401, 409, 419,
1764 421, 431, 433, 439, 443, 449, 457, 461,
1765 463, 467, 479, 487, 491, 499, 503, 509,
1766 521, 523, 541, 547, 557, 563, 569, 571,
1767 577, 587, 593, 599, 601, 607, 613, 617,
1768 619, 631, 641, 643, 647, 653, 659, 661,
1769 673, 677, 683, 691, 701, 709, 719, 727,
1770 733, 739, 743, 751, 757, 761, 769, 773,
1771 787, 797, 809, 811, 821, 823, 827, 829,
1772 839, 853, 857, 859, 863, 877, 881, 883,
1773 887, 907, 911, 919, 929, 937, 941, 947,
1774 953, 967, 971, 977, 983, 991, 997, -103
1775};
1776
1777/*
1778 * Miller-Rabin primality test (HAC 4.24)
1779 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001780int mpi_is_prime( mpi *X,
1781 int (*f_rng)(void *, unsigned char *, size_t),
1782 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001783{
Paul Bakker23986e52011-04-24 08:57:21 +00001784 int ret, xs;
1785 size_t i, j, n, s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001786 mpi W, R, T, A, RR;
Paul Bakker5121ce52009-01-03 21:22:43 +00001787
Paul Bakker48eab262009-06-25 21:25:49 +00001788 if( mpi_cmp_int( X, 0 ) == 0 ||
1789 mpi_cmp_int( X, 1 ) == 0 )
1790 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1791
1792 if( mpi_cmp_int( X, 2 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001793 return( 0 );
1794
Paul Bakker6c591fa2011-05-05 11:49:20 +00001795 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
1796 mpi_init( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001797
1798 xs = X->s; X->s = 1;
1799
1800 /*
1801 * test trivial factors first
1802 */
1803 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001804 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001805
1806 for( i = 0; small_prime[i] > 0; i++ )
1807 {
Paul Bakkera755ca12011-04-24 09:11:17 +00001808 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001809
1810 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
1811 return( 0 );
1812
1813 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1814
1815 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001816 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001817 }
1818
1819 /*
1820 * W = |X| - 1
1821 * R = W >> lsb( W )
1822 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001823 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001824 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001825 MPI_CHK( mpi_copy( &R, &W ) );
1826 MPI_CHK( mpi_shift_r( &R, s ) );
1827
1828 i = mpi_msb( X );
1829 /*
1830 * HAC, table 4.4
1831 */
1832 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1833 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1834 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1835
1836 for( i = 0; i < n; i++ )
1837 {
1838 /*
1839 * pick a random A, 1 < A < |X| - 1
1840 */
Paul Bakker901c6562012-04-20 13:25:38 +00001841 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001842
Paul Bakkerb94081b2011-01-05 15:53:06 +00001843 if( mpi_cmp_mpi( &A, &W ) >= 0 )
1844 {
1845 j = mpi_msb( &A ) - mpi_msb( &W );
1846 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1847 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001848 A.p[0] |= 3;
1849
1850 /*
1851 * A = A^R mod |X|
1852 */
1853 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1854
1855 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1856 mpi_cmp_int( &A, 1 ) == 0 )
1857 continue;
1858
1859 j = 1;
1860 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1861 {
1862 /*
1863 * A = A * A mod |X|
1864 */
1865 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1866 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1867
1868 if( mpi_cmp_int( &A, 1 ) == 0 )
1869 break;
1870
1871 j++;
1872 }
1873
1874 /*
1875 * not prime if A != |X| - 1 or A == 1
1876 */
1877 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1878 mpi_cmp_int( &A, 1 ) == 0 )
1879 {
Paul Bakker40e46942009-01-03 21:51:57 +00001880 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001881 break;
1882 }
1883 }
1884
1885cleanup:
1886
1887 X->s = xs;
1888
Paul Bakker6c591fa2011-05-05 11:49:20 +00001889 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
1890 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001891
1892 return( ret );
1893}
1894
1895/*
1896 * Prime number generation
1897 */
Paul Bakker23986e52011-04-24 08:57:21 +00001898int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001899 int (*f_rng)(void *, unsigned char *, size_t),
1900 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001901{
Paul Bakker23986e52011-04-24 08:57:21 +00001902 int ret;
1903 size_t k, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001904 mpi Y;
1905
Paul Bakkerfe3256e2011-11-25 12:11:43 +00001906 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00001907 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001908
Paul Bakker6c591fa2011-05-05 11:49:20 +00001909 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001910
1911 n = BITS_TO_LIMBS( nbits );
1912
Paul Bakker901c6562012-04-20 13:25:38 +00001913 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001914
1915 k = mpi_msb( X );
1916 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
1917 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
1918
1919 X->p[0] |= 3;
1920
1921 if( dh_flag == 0 )
1922 {
1923 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
1924 {
Paul Bakker40e46942009-01-03 21:51:57 +00001925 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001926 goto cleanup;
1927
1928 MPI_CHK( mpi_add_int( X, X, 2 ) );
1929 }
1930 }
1931 else
1932 {
1933 MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
1934 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1935
1936 while( 1 )
1937 {
1938 if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
1939 {
1940 if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
1941 break;
1942
Paul Bakker40e46942009-01-03 21:51:57 +00001943 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001944 goto cleanup;
1945 }
1946
Paul Bakker40e46942009-01-03 21:51:57 +00001947 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001948 goto cleanup;
1949
1950 MPI_CHK( mpi_add_int( &Y, X, 1 ) );
1951 MPI_CHK( mpi_add_int( X, X, 2 ) );
1952 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1953 }
1954 }
1955
1956cleanup:
1957
Paul Bakker6c591fa2011-05-05 11:49:20 +00001958 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001959
1960 return( ret );
1961}
1962
1963#endif
1964
Paul Bakker40e46942009-01-03 21:51:57 +00001965#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00001966
Paul Bakker23986e52011-04-24 08:57:21 +00001967#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001968
1969static const int gcd_pairs[GCD_PAIR_COUNT][3] =
1970{
1971 { 693, 609, 21 },
1972 { 1764, 868, 28 },
1973 { 768454923, 542167814, 1 }
1974};
1975
Paul Bakker5121ce52009-01-03 21:22:43 +00001976/*
1977 * Checkup routine
1978 */
1979int mpi_self_test( int verbose )
1980{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001981 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001982 mpi A, E, N, X, Y, U, V;
1983
Paul Bakker6c591fa2011-05-05 11:49:20 +00001984 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
1985 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00001986
1987 MPI_CHK( mpi_read_string( &A, 16,
1988 "EFE021C2645FD1DC586E69184AF4A31E" \
1989 "D5F53E93B5F123FA41680867BA110131" \
1990 "944FE7952E2517337780CB0DB80E61AA" \
1991 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
1992
1993 MPI_CHK( mpi_read_string( &E, 16,
1994 "B2E7EFD37075B9F03FF989C7C5051C20" \
1995 "34D2A323810251127E7BF8625A4F49A5" \
1996 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
1997 "5B5C25763222FEFCCFC38B832366C29E" ) );
1998
1999 MPI_CHK( mpi_read_string( &N, 16,
2000 "0066A198186C18C10B2F5ED9B522752A" \
2001 "9830B69916E535C8F047518A889A43A5" \
2002 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2003
2004 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2005
2006 MPI_CHK( mpi_read_string( &U, 16,
2007 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2008 "9E857EA95A03512E2BAE7391688D264A" \
2009 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2010 "8001B72E848A38CAE1C65F78E56ABDEF" \
2011 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2012 "ECF677152EF804370C1A305CAF3B5BF1" \
2013 "30879B56C61DE584A0F53A2447A51E" ) );
2014
2015 if( verbose != 0 )
2016 printf( " MPI test #1 (mul_mpi): " );
2017
2018 if( mpi_cmp_mpi( &X, &U ) != 0 )
2019 {
2020 if( verbose != 0 )
2021 printf( "failed\n" );
2022
2023 return( 1 );
2024 }
2025
2026 if( verbose != 0 )
2027 printf( "passed\n" );
2028
2029 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2030
2031 MPI_CHK( mpi_read_string( &U, 16,
2032 "256567336059E52CAE22925474705F39A94" ) );
2033
2034 MPI_CHK( mpi_read_string( &V, 16,
2035 "6613F26162223DF488E9CD48CC132C7A" \
2036 "0AC93C701B001B092E4E5B9F73BCD27B" \
2037 "9EE50D0657C77F374E903CDFA4C642" ) );
2038
2039 if( verbose != 0 )
2040 printf( " MPI test #2 (div_mpi): " );
2041
2042 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2043 mpi_cmp_mpi( &Y, &V ) != 0 )
2044 {
2045 if( verbose != 0 )
2046 printf( "failed\n" );
2047
2048 return( 1 );
2049 }
2050
2051 if( verbose != 0 )
2052 printf( "passed\n" );
2053
2054 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2055
2056 MPI_CHK( mpi_read_string( &U, 16,
2057 "36E139AEA55215609D2816998ED020BB" \
2058 "BD96C37890F65171D948E9BC7CBAA4D9" \
2059 "325D24D6A3C12710F10A09FA08AB87" ) );
2060
2061 if( verbose != 0 )
2062 printf( " MPI test #3 (exp_mod): " );
2063
2064 if( mpi_cmp_mpi( &X, &U ) != 0 )
2065 {
2066 if( verbose != 0 )
2067 printf( "failed\n" );
2068
2069 return( 1 );
2070 }
2071
2072 if( verbose != 0 )
2073 printf( "passed\n" );
2074
Paul Bakker5690efc2011-05-26 13:16:06 +00002075#if defined(POLARSSL_GENPRIME)
Paul Bakker5121ce52009-01-03 21:22:43 +00002076 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2077
2078 MPI_CHK( mpi_read_string( &U, 16,
2079 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2080 "C3DBA76456363A10869622EAC2DD84EC" \
2081 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2082
2083 if( verbose != 0 )
2084 printf( " MPI test #4 (inv_mod): " );
2085
2086 if( mpi_cmp_mpi( &X, &U ) != 0 )
2087 {
2088 if( verbose != 0 )
2089 printf( "failed\n" );
2090
2091 return( 1 );
2092 }
2093
2094 if( verbose != 0 )
2095 printf( "passed\n" );
Paul Bakker5690efc2011-05-26 13:16:06 +00002096#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002097
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002098 if( verbose != 0 )
2099 printf( " MPI test #5 (simple gcd): " );
2100
2101 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2102 {
2103 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002104 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002105
Paul Bakker23986e52011-04-24 08:57:21 +00002106 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002107
Paul Bakker23986e52011-04-24 08:57:21 +00002108 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2109 {
2110 if( verbose != 0 )
2111 printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002112
Paul Bakker23986e52011-04-24 08:57:21 +00002113 return( 1 );
2114 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002115 }
2116
2117 if( verbose != 0 )
2118 printf( "passed\n" );
2119
Paul Bakker5121ce52009-01-03 21:22:43 +00002120cleanup:
2121
2122 if( ret != 0 && verbose != 0 )
2123 printf( "Unexpected error, return code = %08X\n", ret );
2124
Paul Bakker6c591fa2011-05-05 11:49:20 +00002125 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2126 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002127
2128 if( verbose != 0 )
2129 printf( "\n" );
2130
2131 return( ret );
2132}
2133
2134#endif
2135
2136#endif