blob: eb0fb51d8b0477dcd3265b62fcf1683aeec5abd4 [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
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100614 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
615 return mpi_lset( X, 0 );
616
Paul Bakker5121ce52009-01-03 21:22:43 +0000617 /*
618 * shift by count / limb_size
619 */
620 if( v0 > 0 )
621 {
622 for( i = 0; i < X->n - v0; i++ )
623 X->p[i] = X->p[i + v0];
624
625 for( ; i < X->n; i++ )
626 X->p[i] = 0;
627 }
628
629 /*
630 * shift by count % limb_size
631 */
632 if( v1 > 0 )
633 {
Paul Bakker23986e52011-04-24 08:57:21 +0000634 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000635 {
Paul Bakker23986e52011-04-24 08:57:21 +0000636 r1 = X->p[i - 1] << (biL - v1);
637 X->p[i - 1] >>= v1;
638 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000639 r0 = r1;
640 }
641 }
642
643 return( 0 );
644}
645
646/*
647 * Compare unsigned values
648 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000649int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000650{
Paul Bakker23986e52011-04-24 08:57:21 +0000651 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000652
Paul Bakker23986e52011-04-24 08:57:21 +0000653 for( i = X->n; i > 0; i-- )
654 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000655 break;
656
Paul Bakker23986e52011-04-24 08:57:21 +0000657 for( j = Y->n; j > 0; j-- )
658 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000659 break;
660
Paul Bakker23986e52011-04-24 08:57:21 +0000661 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000662 return( 0 );
663
664 if( i > j ) return( 1 );
665 if( j > i ) return( -1 );
666
Paul Bakker23986e52011-04-24 08:57:21 +0000667 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000668 {
Paul Bakker23986e52011-04-24 08:57:21 +0000669 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
670 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000671 }
672
673 return( 0 );
674}
675
676/*
677 * Compare signed values
678 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000679int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000680{
Paul Bakker23986e52011-04-24 08:57:21 +0000681 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000682
Paul Bakker23986e52011-04-24 08:57:21 +0000683 for( i = X->n; i > 0; i-- )
684 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000685 break;
686
Paul Bakker23986e52011-04-24 08:57:21 +0000687 for( j = Y->n; j > 0; j-- )
688 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000689 break;
690
Paul Bakker23986e52011-04-24 08:57:21 +0000691 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000692 return( 0 );
693
694 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000695 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000696
697 if( X->s > 0 && Y->s < 0 ) return( 1 );
698 if( Y->s > 0 && X->s < 0 ) return( -1 );
699
Paul Bakker23986e52011-04-24 08:57:21 +0000700 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000701 {
Paul Bakker23986e52011-04-24 08:57:21 +0000702 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
703 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000704 }
705
706 return( 0 );
707}
708
709/*
710 * Compare signed values
711 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000712int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000713{
714 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000715 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000716
717 *p = ( z < 0 ) ? -z : z;
718 Y.s = ( z < 0 ) ? -1 : 1;
719 Y.n = 1;
720 Y.p = p;
721
722 return( mpi_cmp_mpi( X, &Y ) );
723}
724
725/*
726 * Unsigned addition: X = |A| + |B| (HAC 14.7)
727 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000728int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000729{
Paul Bakker23986e52011-04-24 08:57:21 +0000730 int ret;
731 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000732 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000733
734 if( X == B )
735 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000736 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000737 }
738
739 if( X != A )
740 MPI_CHK( mpi_copy( X, A ) );
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000741
742 /*
743 * X should always be positive as a result of unsigned additions.
744 */
745 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000746
Paul Bakker23986e52011-04-24 08:57:21 +0000747 for( j = B->n; j > 0; j-- )
748 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000749 break;
750
Paul Bakker23986e52011-04-24 08:57:21 +0000751 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000752
753 o = B->p; p = X->p; c = 0;
754
Paul Bakker23986e52011-04-24 08:57:21 +0000755 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000756 {
757 *p += c; c = ( *p < c );
758 *p += *o; c += ( *p < *o );
759 }
760
761 while( c != 0 )
762 {
763 if( i >= X->n )
764 {
765 MPI_CHK( mpi_grow( X, i + 1 ) );
766 p = X->p + i;
767 }
768
Paul Bakker2d319fd2012-09-16 21:34:26 +0000769 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000770 }
771
772cleanup:
773
774 return( ret );
775}
776
777/*
778 * Helper for mpi substraction
779 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000780static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000781{
Paul Bakker23986e52011-04-24 08:57:21 +0000782 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000783 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000784
785 for( i = c = 0; i < n; i++, s++, d++ )
786 {
787 z = ( *d < c ); *d -= c;
788 c = ( *d < *s ) + z; *d -= *s;
789 }
790
791 while( c != 0 )
792 {
793 z = ( *d < c ); *d -= c;
794 c = z; i++; d++;
795 }
796}
797
798/*
799 * Unsigned substraction: X = |A| - |B| (HAC 14.9)
800 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000801int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000802{
803 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000804 int ret;
805 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000806
807 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000808 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000809
Paul Bakker6c591fa2011-05-05 11:49:20 +0000810 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000811
812 if( X == B )
813 {
814 MPI_CHK( mpi_copy( &TB, B ) );
815 B = &TB;
816 }
817
818 if( X != A )
819 MPI_CHK( mpi_copy( X, A ) );
820
Paul Bakker1ef7a532009-06-20 10:50:55 +0000821 /*
822 * X should always be positive as a result of unsigned substractions.
823 */
824 X->s = 1;
825
Paul Bakker5121ce52009-01-03 21:22:43 +0000826 ret = 0;
827
Paul Bakker23986e52011-04-24 08:57:21 +0000828 for( n = B->n; n > 0; n-- )
829 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000830 break;
831
Paul Bakker23986e52011-04-24 08:57:21 +0000832 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000833
834cleanup:
835
Paul Bakker6c591fa2011-05-05 11:49:20 +0000836 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000837
838 return( ret );
839}
840
841/*
842 * Signed addition: X = A + B
843 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000844int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000845{
846 int ret, s = A->s;
847
848 if( A->s * B->s < 0 )
849 {
850 if( mpi_cmp_abs( A, B ) >= 0 )
851 {
852 MPI_CHK( mpi_sub_abs( X, A, B ) );
853 X->s = s;
854 }
855 else
856 {
857 MPI_CHK( mpi_sub_abs( X, B, A ) );
858 X->s = -s;
859 }
860 }
861 else
862 {
863 MPI_CHK( mpi_add_abs( X, A, B ) );
864 X->s = s;
865 }
866
867cleanup:
868
869 return( ret );
870}
871
872/*
873 * Signed substraction: X = A - B
874 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000875int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000876{
877 int ret, s = A->s;
878
879 if( A->s * B->s > 0 )
880 {
881 if( mpi_cmp_abs( A, B ) >= 0 )
882 {
883 MPI_CHK( mpi_sub_abs( X, A, B ) );
884 X->s = s;
885 }
886 else
887 {
888 MPI_CHK( mpi_sub_abs( X, B, A ) );
889 X->s = -s;
890 }
891 }
892 else
893 {
894 MPI_CHK( mpi_add_abs( X, A, B ) );
895 X->s = s;
896 }
897
898cleanup:
899
900 return( ret );
901}
902
903/*
904 * Signed addition: X = A + b
905 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000906int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000907{
908 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000909 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000910
911 p[0] = ( b < 0 ) ? -b : b;
912 _B.s = ( b < 0 ) ? -1 : 1;
913 _B.n = 1;
914 _B.p = p;
915
916 return( mpi_add_mpi( X, A, &_B ) );
917}
918
919/*
920 * Signed substraction: X = A - b
921 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000922int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000923{
924 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000925 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000926
927 p[0] = ( b < 0 ) ? -b : b;
928 _B.s = ( b < 0 ) ? -1 : 1;
929 _B.n = 1;
930 _B.p = p;
931
932 return( mpi_sub_mpi( X, A, &_B ) );
933}
934
935/*
936 * Helper for mpi multiplication
Paul Bakker52b845b2013-06-14 11:36:56 +0200937 */
938static
939#if defined(__APPLE__) && defined(__arm__)
940/*
941 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
942 * appears to need this to prevent bad ARM code generation at -O3.
943 */
944__attribute__ ((noinline))
945#endif
946void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000947{
Paul Bakkera755ca12011-04-24 09:11:17 +0000948 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000949
950#if defined(MULADDC_HUIT)
951 for( ; i >= 8; i -= 8 )
952 {
953 MULADDC_INIT
954 MULADDC_HUIT
955 MULADDC_STOP
956 }
957
958 for( ; i > 0; i-- )
959 {
960 MULADDC_INIT
961 MULADDC_CORE
962 MULADDC_STOP
963 }
964#else
965 for( ; i >= 16; i -= 16 )
966 {
967 MULADDC_INIT
968 MULADDC_CORE MULADDC_CORE
969 MULADDC_CORE MULADDC_CORE
970 MULADDC_CORE MULADDC_CORE
971 MULADDC_CORE MULADDC_CORE
972
973 MULADDC_CORE MULADDC_CORE
974 MULADDC_CORE MULADDC_CORE
975 MULADDC_CORE MULADDC_CORE
976 MULADDC_CORE MULADDC_CORE
977 MULADDC_STOP
978 }
979
980 for( ; i >= 8; i -= 8 )
981 {
982 MULADDC_INIT
983 MULADDC_CORE MULADDC_CORE
984 MULADDC_CORE MULADDC_CORE
985
986 MULADDC_CORE MULADDC_CORE
987 MULADDC_CORE MULADDC_CORE
988 MULADDC_STOP
989 }
990
991 for( ; i > 0; i-- )
992 {
993 MULADDC_INIT
994 MULADDC_CORE
995 MULADDC_STOP
996 }
997#endif
998
999 t++;
1000
1001 do {
1002 *d += c; c = ( *d < c ); d++;
1003 }
1004 while( c != 0 );
1005}
1006
1007/*
1008 * Baseline multiplication: X = A * B (HAC 14.12)
1009 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001010int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001011{
Paul Bakker23986e52011-04-24 08:57:21 +00001012 int ret;
1013 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001014 mpi TA, TB;
1015
Paul Bakker6c591fa2011-05-05 11:49:20 +00001016 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001017
1018 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1019 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1020
Paul Bakker23986e52011-04-24 08:57:21 +00001021 for( i = A->n; i > 0; i-- )
1022 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001023 break;
1024
Paul Bakker23986e52011-04-24 08:57:21 +00001025 for( j = B->n; j > 0; j-- )
1026 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001027 break;
1028
Paul Bakker23986e52011-04-24 08:57:21 +00001029 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001030 MPI_CHK( mpi_lset( X, 0 ) );
1031
Paul Bakker23986e52011-04-24 08:57:21 +00001032 for( i++; j > 0; j-- )
1033 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001034
1035 X->s = A->s * B->s;
1036
1037cleanup:
1038
Paul Bakker6c591fa2011-05-05 11:49:20 +00001039 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001040
1041 return( ret );
1042}
1043
1044/*
1045 * Baseline multiplication: X = A * b
1046 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001047int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001048{
1049 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001050 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001051
1052 _B.s = 1;
1053 _B.n = 1;
1054 _B.p = p;
1055 p[0] = b;
1056
1057 return( mpi_mul_mpi( X, A, &_B ) );
1058}
1059
1060/*
1061 * Division by mpi: A = Q * B + R (HAC 14.20)
1062 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001063int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001064{
Paul Bakker23986e52011-04-24 08:57:21 +00001065 int ret;
1066 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001067 mpi X, Y, Z, T1, T2;
1068
1069 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001070 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001071
Paul Bakker6c591fa2011-05-05 11:49:20 +00001072 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1073 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001074
1075 if( mpi_cmp_abs( A, B ) < 0 )
1076 {
1077 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1078 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1079 return( 0 );
1080 }
1081
1082 MPI_CHK( mpi_copy( &X, A ) );
1083 MPI_CHK( mpi_copy( &Y, B ) );
1084 X.s = Y.s = 1;
1085
1086 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1087 MPI_CHK( mpi_lset( &Z, 0 ) );
1088 MPI_CHK( mpi_grow( &T1, 2 ) );
1089 MPI_CHK( mpi_grow( &T2, 3 ) );
1090
1091 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001092 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001093 {
1094 k = biL - 1 - k;
1095 MPI_CHK( mpi_shift_l( &X, k ) );
1096 MPI_CHK( mpi_shift_l( &Y, k ) );
1097 }
1098 else k = 0;
1099
1100 n = X.n - 1;
1101 t = Y.n - 1;
Paul Bakkerc110d022012-10-19 12:15:08 +00001102 MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001103
1104 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1105 {
1106 Z.p[n - t]++;
Paul Bakker78e81962013-12-31 11:16:03 +01001107 MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001108 }
Paul Bakker78e81962013-12-31 11:16:03 +01001109 MPI_CHK( mpi_shift_r( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001110
1111 for( i = n; i > t ; i-- )
1112 {
1113 if( X.p[i] >= Y.p[t] )
1114 Z.p[i - t - 1] = ~0;
1115 else
1116 {
Manuel Pégourié-Gonnard57291a72014-03-14 09:21:20 +01001117 /*
Manuel Pégourié-Gonnarda9f86e02014-03-14 18:23:26 +01001118 * The version of Clang shipped by Apple with Mavericks around
1119 * 2014-03 can't handle 128-bit division properly. Disable
1120 * 128-bits division for this version. Let's be optimistic and
1121 * assume it'll be fixed in the next minor version (next
1122 * patchlevel is probably a bit too optimistic).
Manuel Pégourié-Gonnard57291a72014-03-14 09:21:20 +01001123 */
Manuel Pégourié-Gonnarda9f86e02014-03-14 18:23:26 +01001124#if defined(POLARSSL_HAVE_UDBL) && \
1125 ! ( defined(__x86_64__) && defined(__APPLE__) && \
1126 defined(__clang_major__) && __clang_major__ == 5 && \
1127 defined(__clang_minor__) && __clang_minor__ == 0 )
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001128 t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001129
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001130 r = (t_udbl) X.p[i] << biL;
1131 r |= (t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001132 r /= Y.p[t];
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001133 if( r > ((t_udbl) 1 << biL) - 1)
1134 r = ((t_udbl) 1 << biL) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001135
Paul Bakkera755ca12011-04-24 09:11:17 +00001136 Z.p[i - t - 1] = (t_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001137#else
1138 /*
1139 * __udiv_qrnnd_c, from gmp/longlong.h
1140 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001141 t_uint q0, q1, r0, r1;
1142 t_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001143
1144 d = Y.p[t];
1145 d0 = ( d << biH ) >> biH;
1146 d1 = ( d >> biH );
1147
1148 q1 = X.p[i] / d1;
1149 r1 = X.p[i] - d1 * q1;
1150 r1 <<= biH;
1151 r1 |= ( X.p[i - 1] >> biH );
1152
1153 m = q1 * d0;
1154 if( r1 < m )
1155 {
1156 q1--, r1 += d;
1157 while( r1 >= d && r1 < m )
1158 q1--, r1 += d;
1159 }
1160 r1 -= m;
1161
1162 q0 = r1 / d1;
1163 r0 = r1 - d1 * q0;
1164 r0 <<= biH;
1165 r0 |= ( X.p[i - 1] << biH ) >> biH;
1166
1167 m = q0 * d0;
1168 if( r0 < m )
1169 {
1170 q0--, r0 += d;
1171 while( r0 >= d && r0 < m )
1172 q0--, r0 += d;
1173 }
1174 r0 -= m;
1175
1176 Z.p[i - t - 1] = ( q1 << biH ) | q0;
1177#endif
1178 }
1179
1180 Z.p[i - t - 1]++;
1181 do
1182 {
1183 Z.p[i - t - 1]--;
1184
1185 MPI_CHK( mpi_lset( &T1, 0 ) );
1186 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1187 T1.p[1] = Y.p[t];
1188 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1189
1190 MPI_CHK( mpi_lset( &T2, 0 ) );
1191 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1192 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1193 T2.p[2] = X.p[i];
1194 }
1195 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1196
1197 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1198 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1199 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1200
1201 if( mpi_cmp_int( &X, 0 ) < 0 )
1202 {
1203 MPI_CHK( mpi_copy( &T1, &Y ) );
1204 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1205 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1206 Z.p[i - t - 1]--;
1207 }
1208 }
1209
1210 if( Q != NULL )
1211 {
Paul Bakker78e81962013-12-31 11:16:03 +01001212 MPI_CHK( mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001213 Q->s = A->s * B->s;
1214 }
1215
1216 if( R != NULL )
1217 {
Paul Bakker78e81962013-12-31 11:16:03 +01001218 MPI_CHK( mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001219 X.s = A->s;
Paul Bakker78e81962013-12-31 11:16:03 +01001220 MPI_CHK( mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001221
Paul Bakker5121ce52009-01-03 21:22:43 +00001222 if( mpi_cmp_int( R, 0 ) == 0 )
1223 R->s = 1;
1224 }
1225
1226cleanup:
1227
Paul Bakker6c591fa2011-05-05 11:49:20 +00001228 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1229 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001230
1231 return( ret );
1232}
1233
1234/*
1235 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001236 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001237int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001238{
1239 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001240 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001241
1242 p[0] = ( b < 0 ) ? -b : b;
1243 _B.s = ( b < 0 ) ? -1 : 1;
1244 _B.n = 1;
1245 _B.p = p;
1246
1247 return( mpi_div_mpi( Q, R, A, &_B ) );
1248}
1249
1250/*
1251 * Modulo: R = A mod B
1252 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001253int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001254{
1255 int ret;
1256
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001257 if( mpi_cmp_int( B, 0 ) < 0 )
1258 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1259
Paul Bakker5121ce52009-01-03 21:22:43 +00001260 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1261
1262 while( mpi_cmp_int( R, 0 ) < 0 )
1263 MPI_CHK( mpi_add_mpi( R, R, B ) );
1264
1265 while( mpi_cmp_mpi( R, B ) >= 0 )
1266 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1267
1268cleanup:
1269
1270 return( ret );
1271}
1272
1273/*
1274 * Modulo: r = A mod b
1275 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001276int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001277{
Paul Bakker23986e52011-04-24 08:57:21 +00001278 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001279 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001280
1281 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001282 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001283
1284 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001285 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001286
1287 /*
1288 * handle trivial cases
1289 */
1290 if( b == 1 )
1291 {
1292 *r = 0;
1293 return( 0 );
1294 }
1295
1296 if( b == 2 )
1297 {
1298 *r = A->p[0] & 1;
1299 return( 0 );
1300 }
1301
1302 /*
1303 * general case
1304 */
Paul Bakker23986e52011-04-24 08:57:21 +00001305 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001306 {
Paul Bakker23986e52011-04-24 08:57:21 +00001307 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001308 y = ( y << biH ) | ( x >> biH );
1309 z = y / b;
1310 y -= z * b;
1311
1312 x <<= biH;
1313 y = ( y << biH ) | ( x >> biH );
1314 z = y / b;
1315 y -= z * b;
1316 }
1317
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001318 /*
1319 * If A is negative, then the current y represents a negative value.
1320 * Flipping it to the positive side.
1321 */
1322 if( A->s < 0 && y != 0 )
1323 y = b - y;
1324
Paul Bakker5121ce52009-01-03 21:22:43 +00001325 *r = y;
1326
1327 return( 0 );
1328}
1329
1330/*
1331 * Fast Montgomery initialization (thanks to Tom St Denis)
1332 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001333static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001334{
Paul Bakkera755ca12011-04-24 09:11:17 +00001335 t_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnard397858b2014-03-11 13:47:05 +01001336 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001337
1338 x = m0;
1339 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001340
Manuel Pégourié-Gonnard397858b2014-03-11 13:47:05 +01001341 for( i = biL; i >= 8; i /= 2 )
1342 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001343
1344 *mm = ~x + 1;
1345}
1346
1347/*
1348 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1349 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001350static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001351{
Paul Bakker23986e52011-04-24 08:57:21 +00001352 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001353 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001354
1355 memset( T->p, 0, T->n * ciL );
1356
1357 d = T->p;
1358 n = N->n;
1359 m = ( B->n < n ) ? B->n : n;
1360
1361 for( i = 0; i < n; i++ )
1362 {
1363 /*
1364 * T = (T + u0*B + u1*N) / 2^biL
1365 */
1366 u0 = A->p[i];
1367 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1368
1369 mpi_mul_hlp( m, B->p, d, u0 );
1370 mpi_mul_hlp( n, N->p, d, u1 );
1371
1372 *d++ = u0; d[n + 1] = 0;
1373 }
1374
1375 memcpy( A->p, d, (n + 1) * ciL );
1376
1377 if( mpi_cmp_abs( A, N ) >= 0 )
1378 mpi_sub_hlp( n, N->p, A->p );
1379 else
1380 /* prevent timing attacks */
1381 mpi_sub_hlp( n, A->p, T->p );
1382}
1383
1384/*
1385 * Montgomery reduction: A = A * R^-1 mod N
1386 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001387static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001388{
Paul Bakkera755ca12011-04-24 09:11:17 +00001389 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001390 mpi U;
1391
Paul Bakker8ddb6452013-02-27 14:56:33 +01001392 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001393 U.p = &z;
1394
1395 mpi_montmul( A, &U, N, mm, T );
1396}
1397
1398/*
1399 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1400 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001401int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001402{
Paul Bakker23986e52011-04-24 08:57:21 +00001403 int ret;
1404 size_t wbits, wsize, one = 1;
1405 size_t i, j, nblimbs;
1406 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001407 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001408 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1409 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001410
1411 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001412 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001413
Paul Bakkerf6198c12012-05-16 08:02:29 +00001414 if( mpi_cmp_int( E, 0 ) < 0 )
1415 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1416
1417 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001418 * Init temps and window size
1419 */
1420 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001421 mpi_init( &RR ); mpi_init( &T );
Manuel Pégourié-Gonnard7fd620b2014-01-18 19:05:23 +01001422 mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001423 memset( W, 0, sizeof( W ) );
1424
1425 i = mpi_msb( E );
1426
1427 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1428 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1429
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001430 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1431 wsize = POLARSSL_MPI_WINDOW_SIZE;
1432
Paul Bakker5121ce52009-01-03 21:22:43 +00001433 j = N->n + 1;
1434 MPI_CHK( mpi_grow( X, j ) );
1435 MPI_CHK( mpi_grow( &W[1], j ) );
1436 MPI_CHK( mpi_grow( &T, j * 2 ) );
1437
1438 /*
Paul Bakker50546922012-05-19 08:40:49 +00001439 * Compensate for negative A (and correct at the end)
1440 */
1441 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001442 if( neg )
1443 {
1444 MPI_CHK( mpi_copy( &Apos, A ) );
1445 Apos.s = 1;
1446 A = &Apos;
1447 }
1448
1449 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001450 * If 1st call, pre-compute R^2 mod N
1451 */
1452 if( _RR == NULL || _RR->p == NULL )
1453 {
1454 MPI_CHK( mpi_lset( &RR, 1 ) );
1455 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1456 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1457
1458 if( _RR != NULL )
1459 memcpy( _RR, &RR, sizeof( mpi ) );
1460 }
1461 else
1462 memcpy( &RR, _RR, sizeof( mpi ) );
1463
1464 /*
1465 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1466 */
1467 if( mpi_cmp_mpi( A, N ) >= 0 )
Paul Bakker1dc45f12014-01-23 20:38:35 +01001468 {
1469 MPI_CHK( mpi_mod_mpi( &W[1], A, N ) );
1470 }
1471 else
1472 MPI_CHK( mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001473
1474 mpi_montmul( &W[1], &RR, N, mm, &T );
1475
1476 /*
1477 * X = R^2 * R^-1 mod N = R mod N
1478 */
1479 MPI_CHK( mpi_copy( X, &RR ) );
1480 mpi_montred( X, N, mm, &T );
1481
1482 if( wsize > 1 )
1483 {
1484 /*
1485 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1486 */
Paul Bakker23986e52011-04-24 08:57:21 +00001487 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001488
1489 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1490 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1491
1492 for( i = 0; i < wsize - 1; i++ )
1493 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakkerc3ec63d2013-10-29 16:18:35 +01001494
Paul Bakker5121ce52009-01-03 21:22:43 +00001495 /*
1496 * W[i] = W[i - 1] * W[1]
1497 */
Paul Bakker23986e52011-04-24 08:57:21 +00001498 for( i = j + 1; i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001499 {
1500 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1501 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1502
1503 mpi_montmul( &W[i], &W[1], N, mm, &T );
1504 }
1505 }
1506
1507 nblimbs = E->n;
1508 bufsize = 0;
1509 nbits = 0;
1510 wbits = 0;
1511 state = 0;
1512
1513 while( 1 )
1514 {
1515 if( bufsize == 0 )
1516 {
Paul Bakkerc3ec63d2013-10-29 16:18:35 +01001517 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001518 break;
1519
Paul Bakkerc3ec63d2013-10-29 16:18:35 +01001520 nblimbs--;
1521
Paul Bakkera755ca12011-04-24 09:11:17 +00001522 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001523 }
1524
1525 bufsize--;
1526
1527 ei = (E->p[nblimbs] >> bufsize) & 1;
1528
1529 /*
1530 * skip leading 0s
1531 */
1532 if( ei == 0 && state == 0 )
1533 continue;
1534
1535 if( ei == 0 && state == 1 )
1536 {
1537 /*
1538 * out of window, square X
1539 */
1540 mpi_montmul( X, X, N, mm, &T );
1541 continue;
1542 }
1543
1544 /*
1545 * add ei to current window
1546 */
1547 state = 2;
1548
1549 nbits++;
1550 wbits |= (ei << (wsize - nbits));
1551
1552 if( nbits == wsize )
1553 {
1554 /*
1555 * X = X^wsize R^-1 mod N
1556 */
1557 for( i = 0; i < wsize; i++ )
1558 mpi_montmul( X, X, N, mm, &T );
1559
1560 /*
1561 * X = X * W[wbits] R^-1 mod N
1562 */
1563 mpi_montmul( X, &W[wbits], N, mm, &T );
1564
1565 state--;
1566 nbits = 0;
1567 wbits = 0;
1568 }
1569 }
1570
1571 /*
1572 * process the remaining bits
1573 */
1574 for( i = 0; i < nbits; i++ )
1575 {
1576 mpi_montmul( X, X, N, mm, &T );
1577
1578 wbits <<= 1;
1579
Paul Bakker23986e52011-04-24 08:57:21 +00001580 if( (wbits & (one << wsize)) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001581 mpi_montmul( X, &W[1], N, mm, &T );
1582 }
1583
1584 /*
1585 * X = A^E * R * R^-1 mod N = A^E mod N
1586 */
1587 mpi_montred( X, N, mm, &T );
1588
Paul Bakkerf6198c12012-05-16 08:02:29 +00001589 if( neg )
1590 {
1591 X->s = -1;
Paul Bakker1dc45f12014-01-23 20:38:35 +01001592 MPI_CHK( mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001593 }
1594
Paul Bakker5121ce52009-01-03 21:22:43 +00001595cleanup:
1596
Paul Bakker23986e52011-04-24 08:57:21 +00001597 for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001598 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001599
Paul Bakkerf6198c12012-05-16 08:02:29 +00001600 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001601
Paul Bakker6995efe2014-03-31 12:08:17 +02001602 if( _RR == NULL || _RR->p == NULL )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001603 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001604
1605 return( ret );
1606}
1607
Paul Bakker5121ce52009-01-03 21:22:43 +00001608/*
1609 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1610 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001611int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001612{
Paul Bakker23986e52011-04-24 08:57:21 +00001613 int ret;
1614 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001615 mpi TG, TA, TB;
1616
Paul Bakker6c591fa2011-05-05 11:49:20 +00001617 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001618
Paul Bakker5121ce52009-01-03 21:22:43 +00001619 MPI_CHK( mpi_copy( &TA, A ) );
1620 MPI_CHK( mpi_copy( &TB, B ) );
1621
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001622 lz = mpi_lsb( &TA );
1623 lzt = mpi_lsb( &TB );
1624
1625 if ( lzt < lz )
1626 lz = lzt;
1627
1628 MPI_CHK( mpi_shift_r( &TA, lz ) );
1629 MPI_CHK( mpi_shift_r( &TB, lz ) );
1630
Paul Bakker5121ce52009-01-03 21:22:43 +00001631 TA.s = TB.s = 1;
1632
1633 while( mpi_cmp_int( &TA, 0 ) != 0 )
1634 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001635 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1636 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001637
1638 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1639 {
1640 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1641 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1642 }
1643 else
1644 {
1645 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1646 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1647 }
1648 }
1649
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001650 MPI_CHK( mpi_shift_l( &TB, lz ) );
1651 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001652
1653cleanup:
1654
Paul Bakker6c591fa2011-05-05 11:49:20 +00001655 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001656
1657 return( ret );
1658}
1659
Paul Bakker358d3252014-04-30 16:11:39 +02001660/*
1661 * Fill X with size bytes of random.
1662 *
1663 * Use a temporary bytes representation to make sure the result is the same
1664 * regardless of the platform endianness (usefull when f_rng is actually
1665 * deterministic, eg for tests).
1666 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001667int mpi_fill_random( mpi *X, size_t size,
1668 int (*f_rng)(void *, unsigned char *, size_t),
1669 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001670{
Paul Bakker23986e52011-04-24 08:57:21 +00001671 int ret;
Paul Bakker358d3252014-04-30 16:11:39 +02001672 unsigned char buf[POLARSSL_MPI_MAX_SIZE];
1673
1674 if( size > POLARSSL_MPI_MAX_SIZE )
1675 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001676
Paul Bakker39dfdac2012-02-12 17:17:27 +00001677 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001678 MPI_CHK( mpi_lset( X, 0 ) );
1679
Paul Bakker358d3252014-04-30 16:11:39 +02001680 MPI_CHK( f_rng( p_rng, buf, size ) );
1681 MPI_CHK( mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001682
1683cleanup:
1684 return( ret );
1685}
1686
Paul Bakker5121ce52009-01-03 21:22:43 +00001687/*
1688 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1689 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001690int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001691{
1692 int ret;
1693 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1694
1695 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001696 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001697
Paul Bakker6c591fa2011-05-05 11:49:20 +00001698 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1699 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1700 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001701
1702 MPI_CHK( mpi_gcd( &G, A, N ) );
1703
1704 if( mpi_cmp_int( &G, 1 ) != 0 )
1705 {
Paul Bakker40e46942009-01-03 21:51:57 +00001706 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001707 goto cleanup;
1708 }
1709
1710 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1711 MPI_CHK( mpi_copy( &TU, &TA ) );
1712 MPI_CHK( mpi_copy( &TB, N ) );
1713 MPI_CHK( mpi_copy( &TV, N ) );
1714
1715 MPI_CHK( mpi_lset( &U1, 1 ) );
1716 MPI_CHK( mpi_lset( &U2, 0 ) );
1717 MPI_CHK( mpi_lset( &V1, 0 ) );
1718 MPI_CHK( mpi_lset( &V2, 1 ) );
1719
1720 do
1721 {
1722 while( ( TU.p[0] & 1 ) == 0 )
1723 {
1724 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1725
1726 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1727 {
1728 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1729 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1730 }
1731
1732 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1733 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1734 }
1735
1736 while( ( TV.p[0] & 1 ) == 0 )
1737 {
1738 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1739
1740 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1741 {
1742 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1743 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1744 }
1745
1746 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1747 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1748 }
1749
1750 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1751 {
1752 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1753 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1754 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1755 }
1756 else
1757 {
1758 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1759 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1760 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1761 }
1762 }
1763 while( mpi_cmp_int( &TU, 0 ) != 0 );
1764
1765 while( mpi_cmp_int( &V1, 0 ) < 0 )
1766 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1767
1768 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1769 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1770
1771 MPI_CHK( mpi_copy( X, &V1 ) );
1772
1773cleanup:
1774
Paul Bakker6c591fa2011-05-05 11:49:20 +00001775 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1776 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1777 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001778
1779 return( ret );
1780}
1781
Paul Bakkerd9374b02012-11-02 11:02:58 +00001782#if defined(POLARSSL_GENPRIME)
1783
Paul Bakker5121ce52009-01-03 21:22:43 +00001784static const int small_prime[] =
1785{
1786 3, 5, 7, 11, 13, 17, 19, 23,
1787 29, 31, 37, 41, 43, 47, 53, 59,
1788 61, 67, 71, 73, 79, 83, 89, 97,
1789 101, 103, 107, 109, 113, 127, 131, 137,
1790 139, 149, 151, 157, 163, 167, 173, 179,
1791 181, 191, 193, 197, 199, 211, 223, 227,
1792 229, 233, 239, 241, 251, 257, 263, 269,
1793 271, 277, 281, 283, 293, 307, 311, 313,
1794 317, 331, 337, 347, 349, 353, 359, 367,
1795 373, 379, 383, 389, 397, 401, 409, 419,
1796 421, 431, 433, 439, 443, 449, 457, 461,
1797 463, 467, 479, 487, 491, 499, 503, 509,
1798 521, 523, 541, 547, 557, 563, 569, 571,
1799 577, 587, 593, 599, 601, 607, 613, 617,
1800 619, 631, 641, 643, 647, 653, 659, 661,
1801 673, 677, 683, 691, 701, 709, 719, 727,
1802 733, 739, 743, 751, 757, 761, 769, 773,
1803 787, 797, 809, 811, 821, 823, 827, 829,
1804 839, 853, 857, 859, 863, 877, 881, 883,
1805 887, 907, 911, 919, 929, 937, 941, 947,
1806 953, 967, 971, 977, 983, 991, 997, -103
1807};
1808
1809/*
1810 * Miller-Rabin primality test (HAC 4.24)
1811 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001812int mpi_is_prime( mpi *X,
1813 int (*f_rng)(void *, unsigned char *, size_t),
1814 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001815{
Paul Bakker23986e52011-04-24 08:57:21 +00001816 int ret, xs;
1817 size_t i, j, n, s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001818 mpi W, R, T, A, RR;
Paul Bakker5121ce52009-01-03 21:22:43 +00001819
Paul Bakker48eab262009-06-25 21:25:49 +00001820 if( mpi_cmp_int( X, 0 ) == 0 ||
1821 mpi_cmp_int( X, 1 ) == 0 )
1822 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1823
1824 if( mpi_cmp_int( X, 2 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001825 return( 0 );
1826
Paul Bakker6c591fa2011-05-05 11:49:20 +00001827 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
1828 mpi_init( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001829
1830 xs = X->s; X->s = 1;
1831
1832 /*
1833 * test trivial factors first
1834 */
1835 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001836 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001837
1838 for( i = 0; small_prime[i] > 0; i++ )
1839 {
Paul Bakkera755ca12011-04-24 09:11:17 +00001840 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001841
1842 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
1843 return( 0 );
1844
1845 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1846
1847 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001848 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001849 }
1850
1851 /*
1852 * W = |X| - 1
1853 * R = W >> lsb( W )
1854 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001855 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001856 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001857 MPI_CHK( mpi_copy( &R, &W ) );
1858 MPI_CHK( mpi_shift_r( &R, s ) );
1859
1860 i = mpi_msb( X );
1861 /*
1862 * HAC, table 4.4
1863 */
1864 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1865 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1866 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1867
1868 for( i = 0; i < n; i++ )
1869 {
1870 /*
1871 * pick a random A, 1 < A < |X| - 1
1872 */
Paul Bakker901c6562012-04-20 13:25:38 +00001873 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001874
Paul Bakkerb94081b2011-01-05 15:53:06 +00001875 if( mpi_cmp_mpi( &A, &W ) >= 0 )
1876 {
1877 j = mpi_msb( &A ) - mpi_msb( &W );
1878 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1879 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001880 A.p[0] |= 3;
1881
1882 /*
1883 * A = A^R mod |X|
1884 */
1885 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1886
1887 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1888 mpi_cmp_int( &A, 1 ) == 0 )
1889 continue;
1890
1891 j = 1;
1892 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1893 {
1894 /*
1895 * A = A * A mod |X|
1896 */
1897 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1898 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1899
1900 if( mpi_cmp_int( &A, 1 ) == 0 )
1901 break;
1902
1903 j++;
1904 }
1905
1906 /*
1907 * not prime if A != |X| - 1 or A == 1
1908 */
1909 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1910 mpi_cmp_int( &A, 1 ) == 0 )
1911 {
Paul Bakker40e46942009-01-03 21:51:57 +00001912 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001913 break;
1914 }
1915 }
1916
1917cleanup:
1918
1919 X->s = xs;
1920
Paul Bakker6c591fa2011-05-05 11:49:20 +00001921 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
1922 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001923
1924 return( ret );
1925}
1926
1927/*
1928 * Prime number generation
1929 */
Paul Bakker23986e52011-04-24 08:57:21 +00001930int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001931 int (*f_rng)(void *, unsigned char *, size_t),
1932 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00001933{
Paul Bakker23986e52011-04-24 08:57:21 +00001934 int ret;
1935 size_t k, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001936 mpi Y;
1937
Paul Bakkerfe3256e2011-11-25 12:11:43 +00001938 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00001939 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001940
Paul Bakker6c591fa2011-05-05 11:49:20 +00001941 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001942
1943 n = BITS_TO_LIMBS( nbits );
1944
Paul Bakker901c6562012-04-20 13:25:38 +00001945 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001946
1947 k = mpi_msb( X );
1948 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
1949 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
1950
1951 X->p[0] |= 3;
1952
1953 if( dh_flag == 0 )
1954 {
1955 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
1956 {
Paul Bakker40e46942009-01-03 21:51:57 +00001957 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001958 goto cleanup;
1959
1960 MPI_CHK( mpi_add_int( X, X, 2 ) );
1961 }
1962 }
1963 else
1964 {
1965 MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
1966 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1967
1968 while( 1 )
1969 {
1970 if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
1971 {
1972 if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
1973 break;
1974
Paul Bakker40e46942009-01-03 21:51:57 +00001975 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001976 goto cleanup;
1977 }
1978
Paul Bakker40e46942009-01-03 21:51:57 +00001979 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001980 goto cleanup;
1981
1982 MPI_CHK( mpi_add_int( &Y, X, 1 ) );
1983 MPI_CHK( mpi_add_int( X, X, 2 ) );
1984 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1985 }
1986 }
1987
1988cleanup:
1989
Paul Bakker6c591fa2011-05-05 11:49:20 +00001990 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001991
1992 return( ret );
1993}
1994
1995#endif
1996
Paul Bakker40e46942009-01-03 21:51:57 +00001997#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00001998
Paul Bakker23986e52011-04-24 08:57:21 +00001999#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002000
2001static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2002{
2003 { 693, 609, 21 },
2004 { 1764, 868, 28 },
2005 { 768454923, 542167814, 1 }
2006};
2007
Paul Bakker5121ce52009-01-03 21:22:43 +00002008/*
2009 * Checkup routine
2010 */
2011int mpi_self_test( int verbose )
2012{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002013 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002014 mpi A, E, N, X, Y, U, V;
2015
Paul Bakker6c591fa2011-05-05 11:49:20 +00002016 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2017 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002018
2019 MPI_CHK( mpi_read_string( &A, 16,
2020 "EFE021C2645FD1DC586E69184AF4A31E" \
2021 "D5F53E93B5F123FA41680867BA110131" \
2022 "944FE7952E2517337780CB0DB80E61AA" \
2023 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2024
2025 MPI_CHK( mpi_read_string( &E, 16,
2026 "B2E7EFD37075B9F03FF989C7C5051C20" \
2027 "34D2A323810251127E7BF8625A4F49A5" \
2028 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2029 "5B5C25763222FEFCCFC38B832366C29E" ) );
2030
2031 MPI_CHK( mpi_read_string( &N, 16,
2032 "0066A198186C18C10B2F5ED9B522752A" \
2033 "9830B69916E535C8F047518A889A43A5" \
2034 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2035
2036 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2037
2038 MPI_CHK( mpi_read_string( &U, 16,
2039 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2040 "9E857EA95A03512E2BAE7391688D264A" \
2041 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2042 "8001B72E848A38CAE1C65F78E56ABDEF" \
2043 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2044 "ECF677152EF804370C1A305CAF3B5BF1" \
2045 "30879B56C61DE584A0F53A2447A51E" ) );
2046
2047 if( verbose != 0 )
2048 printf( " MPI test #1 (mul_mpi): " );
2049
2050 if( mpi_cmp_mpi( &X, &U ) != 0 )
2051 {
2052 if( verbose != 0 )
2053 printf( "failed\n" );
2054
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002055 ret = 1;
2056 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002057 }
2058
2059 if( verbose != 0 )
2060 printf( "passed\n" );
2061
2062 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2063
2064 MPI_CHK( mpi_read_string( &U, 16,
2065 "256567336059E52CAE22925474705F39A94" ) );
2066
2067 MPI_CHK( mpi_read_string( &V, 16,
2068 "6613F26162223DF488E9CD48CC132C7A" \
2069 "0AC93C701B001B092E4E5B9F73BCD27B" \
2070 "9EE50D0657C77F374E903CDFA4C642" ) );
2071
2072 if( verbose != 0 )
2073 printf( " MPI test #2 (div_mpi): " );
2074
2075 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2076 mpi_cmp_mpi( &Y, &V ) != 0 )
2077 {
2078 if( verbose != 0 )
2079 printf( "failed\n" );
2080
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002081 ret = 1;
2082 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002083 }
2084
2085 if( verbose != 0 )
2086 printf( "passed\n" );
2087
2088 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2089
2090 MPI_CHK( mpi_read_string( &U, 16,
2091 "36E139AEA55215609D2816998ED020BB" \
2092 "BD96C37890F65171D948E9BC7CBAA4D9" \
2093 "325D24D6A3C12710F10A09FA08AB87" ) );
2094
2095 if( verbose != 0 )
2096 printf( " MPI test #3 (exp_mod): " );
2097
2098 if( mpi_cmp_mpi( &X, &U ) != 0 )
2099 {
2100 if( verbose != 0 )
2101 printf( "failed\n" );
2102
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002103 ret = 1;
2104 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002105 }
2106
2107 if( verbose != 0 )
2108 printf( "passed\n" );
2109
Paul Bakker5690efc2011-05-26 13:16:06 +00002110#if defined(POLARSSL_GENPRIME)
Paul Bakker5121ce52009-01-03 21:22:43 +00002111 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2112
2113 MPI_CHK( mpi_read_string( &U, 16,
2114 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2115 "C3DBA76456363A10869622EAC2DD84EC" \
2116 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2117
2118 if( verbose != 0 )
2119 printf( " MPI test #4 (inv_mod): " );
2120
2121 if( mpi_cmp_mpi( &X, &U ) != 0 )
2122 {
2123 if( verbose != 0 )
2124 printf( "failed\n" );
2125
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002126 ret = 1;
2127 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002128 }
2129
2130 if( verbose != 0 )
2131 printf( "passed\n" );
Paul Bakker5690efc2011-05-26 13:16:06 +00002132#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002133
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002134 if( verbose != 0 )
2135 printf( " MPI test #5 (simple gcd): " );
2136
2137 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2138 {
2139 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002140 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002141
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002142 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002143
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002144 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2145 {
2146 if( verbose != 0 )
2147 printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002148
Manuel Pégourié-Gonnardd220f8b2014-01-20 10:03:15 +01002149 ret = 1;
2150 goto cleanup;
2151 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002152 }
2153
2154 if( verbose != 0 )
2155 printf( "passed\n" );
2156
Paul Bakker5121ce52009-01-03 21:22:43 +00002157cleanup:
2158
2159 if( ret != 0 && verbose != 0 )
2160 printf( "Unexpected error, return code = %08X\n", ret );
2161
Paul Bakker6c591fa2011-05-05 11:49:20 +00002162 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2163 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002164
2165 if( verbose != 0 )
2166 printf( "\n" );
2167
2168 return( ret );
2169}
2170
2171#endif
2172
2173#endif