blob: 2b6e234950a6314eaffb489f1040c1296bb2163c [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>
41#include <stdarg.h>
42
Paul Bakkerf9688572011-05-05 10:00:45 +000043#define ciL (sizeof(t_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000044#define biL (ciL << 3) /* bits in limb */
45#define biH (ciL << 2) /* half limb size */
46
47/*
48 * Convert between bits/chars and number of limbs
49 */
50#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL)
51#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
52
53/*
54 * Initialize one or more mpi
55 */
56void mpi_init( mpi *X, ... )
57{
58 va_list args;
59
60 va_start( args, X );
61
62 while( X != NULL )
63 {
64 X->s = 1;
65 X->n = 0;
66 X->p = NULL;
67
68 X = va_arg( args, mpi* );
69 }
70
71 va_end( args );
72}
73
74/*
75 * Unallocate one or more mpi
76 */
77void mpi_free( mpi *X, ... )
78{
79 va_list args;
80
81 va_start( args, X );
82
83 while( X != NULL )
84 {
85 if( X->p != NULL )
86 {
87 memset( X->p, 0, X->n * ciL );
88 free( X->p );
89 }
90
91 X->s = 1;
92 X->n = 0;
93 X->p = NULL;
94
95 X = va_arg( args, mpi* );
96 }
97
98 va_end( args );
99}
100
101/*
102 * Enlarge to the specified number of limbs
103 */
Paul Bakker23986e52011-04-24 08:57:21 +0000104int mpi_grow( mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000105{
Paul Bakkera755ca12011-04-24 09:11:17 +0000106 t_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000107
Paul Bakkerf9688572011-05-05 10:00:45 +0000108 if( nblimbs > POLARSSL_MPI_MAX_LIMBS )
109 return( 1 );
110
Paul Bakker5121ce52009-01-03 21:22:43 +0000111 if( X->n < nblimbs )
112 {
Paul Bakkera755ca12011-04-24 09:11:17 +0000113 if( ( p = (t_uint *) malloc( nblimbs * ciL ) ) == NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000114 return( 1 );
115
116 memset( p, 0, nblimbs * ciL );
117
118 if( X->p != NULL )
119 {
120 memcpy( p, X->p, X->n * ciL );
121 memset( X->p, 0, X->n * ciL );
122 free( X->p );
123 }
124
125 X->n = nblimbs;
126 X->p = p;
127 }
128
129 return( 0 );
130}
131
132/*
133 * Copy the contents of Y into X
134 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000135int mpi_copy( mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000136{
Paul Bakker23986e52011-04-24 08:57:21 +0000137 int ret;
138 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000139
140 if( X == Y )
141 return( 0 );
142
143 for( i = Y->n - 1; i > 0; i-- )
144 if( Y->p[i] != 0 )
145 break;
146 i++;
147
148 X->s = Y->s;
149
150 MPI_CHK( mpi_grow( X, i ) );
151
152 memset( X->p, 0, X->n * ciL );
153 memcpy( X->p, Y->p, i * ciL );
154
155cleanup:
156
157 return( ret );
158}
159
160/*
161 * Swap the contents of X and Y
162 */
163void mpi_swap( mpi *X, mpi *Y )
164{
165 mpi T;
166
167 memcpy( &T, X, sizeof( mpi ) );
168 memcpy( X, Y, sizeof( mpi ) );
169 memcpy( Y, &T, sizeof( mpi ) );
170}
171
172/*
173 * Set value from integer
174 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000175int mpi_lset( mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000176{
177 int ret;
178
179 MPI_CHK( mpi_grow( X, 1 ) );
180 memset( X->p, 0, X->n * ciL );
181
182 X->p[0] = ( z < 0 ) ? -z : z;
183 X->s = ( z < 0 ) ? -1 : 1;
184
185cleanup:
186
187 return( ret );
188}
189
190/*
191 * Return the number of least significant bits
192 */
Paul Bakker23986e52011-04-24 08:57:21 +0000193size_t mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000194{
Paul Bakker23986e52011-04-24 08:57:21 +0000195 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000196
197 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000198 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000199 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
200 return( count );
201
202 return( 0 );
203}
204
205/*
206 * Return the number of most significant bits
207 */
Paul Bakker23986e52011-04-24 08:57:21 +0000208size_t mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000209{
Paul Bakker23986e52011-04-24 08:57:21 +0000210 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000211
212 for( i = X->n - 1; i > 0; i-- )
213 if( X->p[i] != 0 )
214 break;
215
Paul Bakker23986e52011-04-24 08:57:21 +0000216 for( j = biL; j > 0; j-- )
217 if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000218 break;
219
Paul Bakker23986e52011-04-24 08:57:21 +0000220 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000221}
222
223/*
224 * Return the total size in bytes
225 */
Paul Bakker23986e52011-04-24 08:57:21 +0000226size_t mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000227{
228 return( ( mpi_msb( X ) + 7 ) >> 3 );
229}
230
231/*
232 * Convert an ASCII character to digit value
233 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000234static int mpi_get_digit( t_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000235{
236 *d = 255;
237
238 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
239 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
240 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
241
Paul Bakkera755ca12011-04-24 09:11:17 +0000242 if( *d >= (t_uint) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000243 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000244
245 return( 0 );
246}
247
248/*
249 * Import from an ASCII string
250 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000251int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000252{
Paul Bakker23986e52011-04-24 08:57:21 +0000253 int ret;
254 size_t i, j, slen, n;
Paul Bakkera755ca12011-04-24 09:11:17 +0000255 t_uint d;
Paul Bakker5121ce52009-01-03 21:22:43 +0000256 mpi T;
257
258 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000259 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000260
261 mpi_init( &T, NULL );
262
Paul Bakkerff60ee62010-03-16 21:09:09 +0000263 slen = strlen( s );
264
Paul Bakker5121ce52009-01-03 21:22:43 +0000265 if( radix == 16 )
266 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000267 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000268
269 MPI_CHK( mpi_grow( X, n ) );
270 MPI_CHK( mpi_lset( X, 0 ) );
271
Paul Bakker23986e52011-04-24 08:57:21 +0000272 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000273 {
Paul Bakker23986e52011-04-24 08:57:21 +0000274 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000275 {
276 X->s = -1;
277 break;
278 }
279
Paul Bakker23986e52011-04-24 08:57:21 +0000280 MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000281 X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
282 }
283 }
284 else
285 {
286 MPI_CHK( mpi_lset( X, 0 ) );
287
Paul Bakkerff60ee62010-03-16 21:09:09 +0000288 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000289 {
290 if( i == 0 && s[i] == '-' )
291 {
292 X->s = -1;
293 continue;
294 }
295
296 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
297 MPI_CHK( mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000298
299 if( X->s == 1 )
300 {
301 MPI_CHK( mpi_add_int( X, &T, d ) );
302 }
303 else
304 {
305 MPI_CHK( mpi_sub_int( X, &T, d ) );
306 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000307 }
308 }
309
310cleanup:
311
312 mpi_free( &T, NULL );
313
314 return( ret );
315}
316
317/*
318 * Helper to write the digits high-order first
319 */
320static int mpi_write_hlp( mpi *X, int radix, char **p )
321{
322 int ret;
Paul Bakkera755ca12011-04-24 09:11:17 +0000323 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000324
325 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000326 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000327
328 MPI_CHK( mpi_mod_int( &r, X, radix ) );
329 MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
330
331 if( mpi_cmp_int( X, 0 ) != 0 )
332 MPI_CHK( mpi_write_hlp( X, radix, p ) );
333
334 if( r < 10 )
335 *(*p)++ = (char)( r + 0x30 );
336 else
337 *(*p)++ = (char)( r + 0x37 );
338
339cleanup:
340
341 return( ret );
342}
343
344/*
345 * Export into an ASCII string
346 */
Paul Bakker23986e52011-04-24 08:57:21 +0000347int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000348{
Paul Bakker23986e52011-04-24 08:57:21 +0000349 int ret = 0;
350 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000351 char *p;
352 mpi T;
353
354 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000355 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000356
357 n = mpi_msb( X );
358 if( radix >= 4 ) n >>= 1;
359 if( radix >= 16 ) n >>= 1;
360 n += 3;
361
362 if( *slen < n )
363 {
364 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000365 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000366 }
367
368 p = s;
369 mpi_init( &T, NULL );
370
371 if( X->s == -1 )
372 *p++ = '-';
373
374 if( radix == 16 )
375 {
Paul Bakker23986e52011-04-24 08:57:21 +0000376 int c;
377 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000378
Paul Bakker23986e52011-04-24 08:57:21 +0000379 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000380 {
Paul Bakker23986e52011-04-24 08:57:21 +0000381 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000382 {
Paul Bakker23986e52011-04-24 08:57:21 +0000383 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000384
Paul Bakker23986e52011-04-24 08:57:21 +0000385 if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000386 continue;
387
388 p += sprintf( p, "%02X", c );
389 k = 1;
390 }
391 }
392 }
393 else
394 {
395 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000396
397 if( T.s == -1 )
398 T.s = 1;
399
Paul Bakker5121ce52009-01-03 21:22:43 +0000400 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
401 }
402
403 *p++ = '\0';
404 *slen = p - s;
405
406cleanup:
407
408 mpi_free( &T, NULL );
409
410 return( ret );
411}
412
Paul Bakker335db3f2011-04-25 15:28:35 +0000413#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000414/*
415 * Read X from an opened file
416 */
417int mpi_read_file( mpi *X, int radix, FILE *fin )
418{
Paul Bakkera755ca12011-04-24 09:11:17 +0000419 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000420 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000421 char *p;
422 char s[1024];
423
424 memset( s, 0, sizeof( s ) );
425 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000426 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000427
428 slen = strlen( s );
429 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
430 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
431
432 p = s + slen;
433 while( --p >= s )
434 if( mpi_get_digit( &d, radix, *p ) != 0 )
435 break;
436
437 return( mpi_read_string( X, radix, p + 1 ) );
438}
439
440/*
441 * Write X into an opened file (or stdout if fout == NULL)
442 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000443int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000444{
Paul Bakker23986e52011-04-24 08:57:21 +0000445 int ret;
446 size_t n, slen, plen;
Paul Bakker08f3c302010-07-08 06:54:25 +0000447 char s[2048];
Paul Bakker5121ce52009-01-03 21:22:43 +0000448
449 n = sizeof( s );
450 memset( s, 0, n );
451 n -= 2;
452
Paul Bakker23986e52011-04-24 08:57:21 +0000453 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000454
455 if( p == NULL ) p = "";
456
457 plen = strlen( p );
458 slen = strlen( s );
459 s[slen++] = '\r';
460 s[slen++] = '\n';
461
462 if( fout != NULL )
463 {
464 if( fwrite( p, 1, plen, fout ) != plen ||
465 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000466 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000467 }
468 else
469 printf( "%s%s", p, s );
470
471cleanup:
472
473 return( ret );
474}
Paul Bakker335db3f2011-04-25 15:28:35 +0000475#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000476
477/*
478 * Import X from unsigned binary data, big endian
479 */
Paul Bakker23986e52011-04-24 08:57:21 +0000480int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000481{
Paul Bakker23986e52011-04-24 08:57:21 +0000482 int ret;
483 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000484
485 for( n = 0; n < buflen; n++ )
486 if( buf[n] != 0 )
487 break;
488
489 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
490 MPI_CHK( mpi_lset( X, 0 ) );
491
Paul Bakker23986e52011-04-24 08:57:21 +0000492 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000493 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000494
495cleanup:
496
497 return( ret );
498}
499
500/*
501 * Export X into unsigned binary data, big endian
502 */
Paul Bakker23986e52011-04-24 08:57:21 +0000503int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000504{
Paul Bakker23986e52011-04-24 08:57:21 +0000505 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000506
507 n = mpi_size( X );
508
509 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000510 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000511
512 memset( buf, 0, buflen );
513
514 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
515 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
516
517 return( 0 );
518}
519
520/*
521 * Left-shift: X <<= count
522 */
Paul Bakker23986e52011-04-24 08:57:21 +0000523int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000524{
Paul Bakker23986e52011-04-24 08:57:21 +0000525 int ret;
526 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000527 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000528
529 v0 = count / (biL );
530 t1 = count & (biL - 1);
531
532 i = mpi_msb( X ) + count;
533
Paul Bakkerf9688572011-05-05 10:00:45 +0000534 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000535 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
536
537 ret = 0;
538
539 /*
540 * shift by count / limb_size
541 */
542 if( v0 > 0 )
543 {
Paul Bakker23986e52011-04-24 08:57:21 +0000544 for( i = X->n; i > v0; i-- )
545 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000546
Paul Bakker23986e52011-04-24 08:57:21 +0000547 for( ; i > 0; i-- )
548 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000549 }
550
551 /*
552 * shift by count % limb_size
553 */
554 if( t1 > 0 )
555 {
556 for( i = v0; i < X->n; i++ )
557 {
558 r1 = X->p[i] >> (biL - t1);
559 X->p[i] <<= t1;
560 X->p[i] |= r0;
561 r0 = r1;
562 }
563 }
564
565cleanup:
566
567 return( ret );
568}
569
570/*
571 * Right-shift: X >>= count
572 */
Paul Bakker23986e52011-04-24 08:57:21 +0000573int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000574{
Paul Bakker23986e52011-04-24 08:57:21 +0000575 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000576 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000577
578 v0 = count / biL;
579 v1 = count & (biL - 1);
580
581 /*
582 * shift by count / limb_size
583 */
584 if( v0 > 0 )
585 {
586 for( i = 0; i < X->n - v0; i++ )
587 X->p[i] = X->p[i + v0];
588
589 for( ; i < X->n; i++ )
590 X->p[i] = 0;
591 }
592
593 /*
594 * shift by count % limb_size
595 */
596 if( v1 > 0 )
597 {
Paul Bakker23986e52011-04-24 08:57:21 +0000598 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000599 {
Paul Bakker23986e52011-04-24 08:57:21 +0000600 r1 = X->p[i - 1] << (biL - v1);
601 X->p[i - 1] >>= v1;
602 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000603 r0 = r1;
604 }
605 }
606
607 return( 0 );
608}
609
610/*
611 * Compare unsigned values
612 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000613int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000614{
Paul Bakker23986e52011-04-24 08:57:21 +0000615 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000616
Paul Bakker23986e52011-04-24 08:57:21 +0000617 for( i = X->n; i > 0; i-- )
618 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000619 break;
620
Paul Bakker23986e52011-04-24 08:57:21 +0000621 for( j = Y->n; j > 0; j-- )
622 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 break;
624
Paul Bakker23986e52011-04-24 08:57:21 +0000625 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000626 return( 0 );
627
628 if( i > j ) return( 1 );
629 if( j > i ) return( -1 );
630
Paul Bakker23986e52011-04-24 08:57:21 +0000631 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000632 {
Paul Bakker23986e52011-04-24 08:57:21 +0000633 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
634 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000635 }
636
637 return( 0 );
638}
639
640/*
641 * Compare signed values
642 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000643int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000644{
Paul Bakker23986e52011-04-24 08:57:21 +0000645 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000646
Paul Bakker23986e52011-04-24 08:57:21 +0000647 for( i = X->n; i > 0; i-- )
648 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000649 break;
650
Paul Bakker23986e52011-04-24 08:57:21 +0000651 for( j = Y->n; j > 0; j-- )
652 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000653 break;
654
Paul Bakker23986e52011-04-24 08:57:21 +0000655 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000656 return( 0 );
657
658 if( i > j ) return( X->s );
659 if( j > i ) return( -X->s );
660
661 if( X->s > 0 && Y->s < 0 ) return( 1 );
662 if( Y->s > 0 && X->s < 0 ) 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( X->s );
667 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000668 }
669
670 return( 0 );
671}
672
673/*
674 * Compare signed values
675 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000676int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000677{
678 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000679 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000680
681 *p = ( z < 0 ) ? -z : z;
682 Y.s = ( z < 0 ) ? -1 : 1;
683 Y.n = 1;
684 Y.p = p;
685
686 return( mpi_cmp_mpi( X, &Y ) );
687}
688
689/*
690 * Unsigned addition: X = |A| + |B| (HAC 14.7)
691 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000692int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000693{
Paul Bakker23986e52011-04-24 08:57:21 +0000694 int ret;
695 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000696 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000697
698 if( X == B )
699 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000700 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000701 }
702
703 if( X != A )
704 MPI_CHK( mpi_copy( X, A ) );
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000705
706 /*
707 * X should always be positive as a result of unsigned additions.
708 */
709 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000710
Paul Bakker23986e52011-04-24 08:57:21 +0000711 for( j = B->n; j > 0; j-- )
712 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000713 break;
714
Paul Bakker23986e52011-04-24 08:57:21 +0000715 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000716
717 o = B->p; p = X->p; c = 0;
718
Paul Bakker23986e52011-04-24 08:57:21 +0000719 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000720 {
721 *p += c; c = ( *p < c );
722 *p += *o; c += ( *p < *o );
723 }
724
725 while( c != 0 )
726 {
727 if( i >= X->n )
728 {
729 MPI_CHK( mpi_grow( X, i + 1 ) );
730 p = X->p + i;
731 }
732
733 *p += c; c = ( *p < c ); i++;
734 }
735
736cleanup:
737
738 return( ret );
739}
740
741/*
742 * Helper for mpi substraction
743 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000744static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000745{
Paul Bakker23986e52011-04-24 08:57:21 +0000746 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000747 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000748
749 for( i = c = 0; i < n; i++, s++, d++ )
750 {
751 z = ( *d < c ); *d -= c;
752 c = ( *d < *s ) + z; *d -= *s;
753 }
754
755 while( c != 0 )
756 {
757 z = ( *d < c ); *d -= c;
758 c = z; i++; d++;
759 }
760}
761
762/*
763 * Unsigned substraction: X = |A| - |B| (HAC 14.9)
764 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000765int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000766{
767 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000768 int ret;
769 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000770
771 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000772 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000773
774 mpi_init( &TB, NULL );
775
776 if( X == B )
777 {
778 MPI_CHK( mpi_copy( &TB, B ) );
779 B = &TB;
780 }
781
782 if( X != A )
783 MPI_CHK( mpi_copy( X, A ) );
784
Paul Bakker1ef7a532009-06-20 10:50:55 +0000785 /*
786 * X should always be positive as a result of unsigned substractions.
787 */
788 X->s = 1;
789
Paul Bakker5121ce52009-01-03 21:22:43 +0000790 ret = 0;
791
Paul Bakker23986e52011-04-24 08:57:21 +0000792 for( n = B->n; n > 0; n-- )
793 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000794 break;
795
Paul Bakker23986e52011-04-24 08:57:21 +0000796 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000797
798cleanup:
799
800 mpi_free( &TB, NULL );
801
802 return( ret );
803}
804
805/*
806 * Signed addition: X = A + B
807 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000808int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000809{
810 int ret, s = A->s;
811
812 if( A->s * B->s < 0 )
813 {
814 if( mpi_cmp_abs( A, B ) >= 0 )
815 {
816 MPI_CHK( mpi_sub_abs( X, A, B ) );
817 X->s = s;
818 }
819 else
820 {
821 MPI_CHK( mpi_sub_abs( X, B, A ) );
822 X->s = -s;
823 }
824 }
825 else
826 {
827 MPI_CHK( mpi_add_abs( X, A, B ) );
828 X->s = s;
829 }
830
831cleanup:
832
833 return( ret );
834}
835
836/*
837 * Signed substraction: X = A - B
838 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000839int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000840{
841 int ret, s = A->s;
842
843 if( A->s * B->s > 0 )
844 {
845 if( mpi_cmp_abs( A, B ) >= 0 )
846 {
847 MPI_CHK( mpi_sub_abs( X, A, B ) );
848 X->s = s;
849 }
850 else
851 {
852 MPI_CHK( mpi_sub_abs( X, B, A ) );
853 X->s = -s;
854 }
855 }
856 else
857 {
858 MPI_CHK( mpi_add_abs( X, A, B ) );
859 X->s = s;
860 }
861
862cleanup:
863
864 return( ret );
865}
866
867/*
868 * Signed addition: X = A + b
869 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000870int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000871{
872 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000873 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000874
875 p[0] = ( b < 0 ) ? -b : b;
876 _B.s = ( b < 0 ) ? -1 : 1;
877 _B.n = 1;
878 _B.p = p;
879
880 return( mpi_add_mpi( X, A, &_B ) );
881}
882
883/*
884 * Signed substraction: X = A - b
885 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000886int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000887{
888 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000889 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000890
891 p[0] = ( b < 0 ) ? -b : b;
892 _B.s = ( b < 0 ) ? -1 : 1;
893 _B.n = 1;
894 _B.p = p;
895
896 return( mpi_sub_mpi( X, A, &_B ) );
897}
898
899/*
900 * Helper for mpi multiplication
901 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000902static void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000903{
Paul Bakkera755ca12011-04-24 09:11:17 +0000904 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000905
906#if defined(MULADDC_HUIT)
907 for( ; i >= 8; i -= 8 )
908 {
909 MULADDC_INIT
910 MULADDC_HUIT
911 MULADDC_STOP
912 }
913
914 for( ; i > 0; i-- )
915 {
916 MULADDC_INIT
917 MULADDC_CORE
918 MULADDC_STOP
919 }
920#else
921 for( ; i >= 16; i -= 16 )
922 {
923 MULADDC_INIT
924 MULADDC_CORE MULADDC_CORE
925 MULADDC_CORE MULADDC_CORE
926 MULADDC_CORE MULADDC_CORE
927 MULADDC_CORE MULADDC_CORE
928
929 MULADDC_CORE MULADDC_CORE
930 MULADDC_CORE MULADDC_CORE
931 MULADDC_CORE MULADDC_CORE
932 MULADDC_CORE MULADDC_CORE
933 MULADDC_STOP
934 }
935
936 for( ; i >= 8; i -= 8 )
937 {
938 MULADDC_INIT
939 MULADDC_CORE MULADDC_CORE
940 MULADDC_CORE MULADDC_CORE
941
942 MULADDC_CORE MULADDC_CORE
943 MULADDC_CORE MULADDC_CORE
944 MULADDC_STOP
945 }
946
947 for( ; i > 0; i-- )
948 {
949 MULADDC_INIT
950 MULADDC_CORE
951 MULADDC_STOP
952 }
953#endif
954
955 t++;
956
957 do {
958 *d += c; c = ( *d < c ); d++;
959 }
960 while( c != 0 );
961}
962
963/*
964 * Baseline multiplication: X = A * B (HAC 14.12)
965 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000966int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000967{
Paul Bakker23986e52011-04-24 08:57:21 +0000968 int ret;
969 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000970 mpi TA, TB;
971
972 mpi_init( &TA, &TB, NULL );
973
974 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
975 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
976
Paul Bakker23986e52011-04-24 08:57:21 +0000977 for( i = A->n; i > 0; i-- )
978 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000979 break;
980
Paul Bakker23986e52011-04-24 08:57:21 +0000981 for( j = B->n; j > 0; j-- )
982 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000983 break;
984
Paul Bakker23986e52011-04-24 08:57:21 +0000985 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000986 MPI_CHK( mpi_lset( X, 0 ) );
987
Paul Bakker23986e52011-04-24 08:57:21 +0000988 for( i++; j > 0; j-- )
989 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000990
991 X->s = A->s * B->s;
992
993cleanup:
994
995 mpi_free( &TB, &TA, NULL );
996
997 return( ret );
998}
999
1000/*
1001 * Baseline multiplication: X = A * b
1002 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001003int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001004{
1005 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001006 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001007
1008 _B.s = 1;
1009 _B.n = 1;
1010 _B.p = p;
1011 p[0] = b;
1012
1013 return( mpi_mul_mpi( X, A, &_B ) );
1014}
1015
1016/*
1017 * Division by mpi: A = Q * B + R (HAC 14.20)
1018 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001019int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001020{
Paul Bakker23986e52011-04-24 08:57:21 +00001021 int ret;
1022 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001023 mpi X, Y, Z, T1, T2;
1024
1025 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001026 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001027
1028 mpi_init( &X, &Y, &Z, &T1, &T2, NULL );
1029
1030 if( mpi_cmp_abs( A, B ) < 0 )
1031 {
1032 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1033 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1034 return( 0 );
1035 }
1036
1037 MPI_CHK( mpi_copy( &X, A ) );
1038 MPI_CHK( mpi_copy( &Y, B ) );
1039 X.s = Y.s = 1;
1040
1041 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1042 MPI_CHK( mpi_lset( &Z, 0 ) );
1043 MPI_CHK( mpi_grow( &T1, 2 ) );
1044 MPI_CHK( mpi_grow( &T2, 3 ) );
1045
1046 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001047 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001048 {
1049 k = biL - 1 - k;
1050 MPI_CHK( mpi_shift_l( &X, k ) );
1051 MPI_CHK( mpi_shift_l( &Y, k ) );
1052 }
1053 else k = 0;
1054
1055 n = X.n - 1;
1056 t = Y.n - 1;
1057 mpi_shift_l( &Y, biL * (n - t) );
1058
1059 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1060 {
1061 Z.p[n - t]++;
1062 mpi_sub_mpi( &X, &X, &Y );
1063 }
1064 mpi_shift_r( &Y, biL * (n - t) );
1065
1066 for( i = n; i > t ; i-- )
1067 {
1068 if( X.p[i] >= Y.p[t] )
1069 Z.p[i - t - 1] = ~0;
1070 else
1071 {
Paul Bakker40e46942009-01-03 21:51:57 +00001072#if defined(POLARSSL_HAVE_LONGLONG)
Paul Bakker5121ce52009-01-03 21:22:43 +00001073 t_dbl r;
1074
1075 r = (t_dbl) X.p[i] << biL;
1076 r |= (t_dbl) X.p[i - 1];
1077 r /= Y.p[t];
1078 if( r > ((t_dbl) 1 << biL) - 1)
1079 r = ((t_dbl) 1 << biL) - 1;
1080
Paul Bakkera755ca12011-04-24 09:11:17 +00001081 Z.p[i - t - 1] = (t_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001082#else
1083 /*
1084 * __udiv_qrnnd_c, from gmp/longlong.h
1085 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001086 t_uint q0, q1, r0, r1;
1087 t_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001088
1089 d = Y.p[t];
1090 d0 = ( d << biH ) >> biH;
1091 d1 = ( d >> biH );
1092
1093 q1 = X.p[i] / d1;
1094 r1 = X.p[i] - d1 * q1;
1095 r1 <<= biH;
1096 r1 |= ( X.p[i - 1] >> biH );
1097
1098 m = q1 * d0;
1099 if( r1 < m )
1100 {
1101 q1--, r1 += d;
1102 while( r1 >= d && r1 < m )
1103 q1--, r1 += d;
1104 }
1105 r1 -= m;
1106
1107 q0 = r1 / d1;
1108 r0 = r1 - d1 * q0;
1109 r0 <<= biH;
1110 r0 |= ( X.p[i - 1] << biH ) >> biH;
1111
1112 m = q0 * d0;
1113 if( r0 < m )
1114 {
1115 q0--, r0 += d;
1116 while( r0 >= d && r0 < m )
1117 q0--, r0 += d;
1118 }
1119 r0 -= m;
1120
1121 Z.p[i - t - 1] = ( q1 << biH ) | q0;
1122#endif
1123 }
1124
1125 Z.p[i - t - 1]++;
1126 do
1127 {
1128 Z.p[i - t - 1]--;
1129
1130 MPI_CHK( mpi_lset( &T1, 0 ) );
1131 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1132 T1.p[1] = Y.p[t];
1133 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1134
1135 MPI_CHK( mpi_lset( &T2, 0 ) );
1136 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1137 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1138 T2.p[2] = X.p[i];
1139 }
1140 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1141
1142 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1143 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1144 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1145
1146 if( mpi_cmp_int( &X, 0 ) < 0 )
1147 {
1148 MPI_CHK( mpi_copy( &T1, &Y ) );
1149 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1150 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1151 Z.p[i - t - 1]--;
1152 }
1153 }
1154
1155 if( Q != NULL )
1156 {
1157 mpi_copy( Q, &Z );
1158 Q->s = A->s * B->s;
1159 }
1160
1161 if( R != NULL )
1162 {
1163 mpi_shift_r( &X, k );
1164 mpi_copy( R, &X );
1165
1166 R->s = A->s;
1167 if( mpi_cmp_int( R, 0 ) == 0 )
1168 R->s = 1;
1169 }
1170
1171cleanup:
1172
1173 mpi_free( &X, &Y, &Z, &T1, &T2, NULL );
1174
1175 return( ret );
1176}
1177
1178/*
1179 * Division by int: A = Q * b + R
1180 *
1181 * Returns 0 if successful
1182 * 1 if memory allocation failed
Paul Bakker40e46942009-01-03 21:51:57 +00001183 * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
Paul Bakker5121ce52009-01-03 21:22:43 +00001184 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001185int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001186{
1187 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001188 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001189
1190 p[0] = ( b < 0 ) ? -b : b;
1191 _B.s = ( b < 0 ) ? -1 : 1;
1192 _B.n = 1;
1193 _B.p = p;
1194
1195 return( mpi_div_mpi( Q, R, A, &_B ) );
1196}
1197
1198/*
1199 * Modulo: R = A mod B
1200 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001201int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001202{
1203 int ret;
1204
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001205 if( mpi_cmp_int( B, 0 ) < 0 )
1206 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1207
Paul Bakker5121ce52009-01-03 21:22:43 +00001208 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1209
1210 while( mpi_cmp_int( R, 0 ) < 0 )
1211 MPI_CHK( mpi_add_mpi( R, R, B ) );
1212
1213 while( mpi_cmp_mpi( R, B ) >= 0 )
1214 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1215
1216cleanup:
1217
1218 return( ret );
1219}
1220
1221/*
1222 * Modulo: r = A mod b
1223 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001224int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001225{
Paul Bakker23986e52011-04-24 08:57:21 +00001226 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001227 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001228
1229 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001230 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001231
1232 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001233 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001234
1235 /*
1236 * handle trivial cases
1237 */
1238 if( b == 1 )
1239 {
1240 *r = 0;
1241 return( 0 );
1242 }
1243
1244 if( b == 2 )
1245 {
1246 *r = A->p[0] & 1;
1247 return( 0 );
1248 }
1249
1250 /*
1251 * general case
1252 */
Paul Bakker23986e52011-04-24 08:57:21 +00001253 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001254 {
Paul Bakker23986e52011-04-24 08:57:21 +00001255 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001256 y = ( y << biH ) | ( x >> biH );
1257 z = y / b;
1258 y -= z * b;
1259
1260 x <<= biH;
1261 y = ( y << biH ) | ( x >> biH );
1262 z = y / b;
1263 y -= z * b;
1264 }
1265
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001266 /*
1267 * If A is negative, then the current y represents a negative value.
1268 * Flipping it to the positive side.
1269 */
1270 if( A->s < 0 && y != 0 )
1271 y = b - y;
1272
Paul Bakker5121ce52009-01-03 21:22:43 +00001273 *r = y;
1274
1275 return( 0 );
1276}
1277
1278/*
1279 * Fast Montgomery initialization (thanks to Tom St Denis)
1280 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001281static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001282{
Paul Bakkera755ca12011-04-24 09:11:17 +00001283 t_uint x, m0 = N->p[0];
Paul Bakker5121ce52009-01-03 21:22:43 +00001284
1285 x = m0;
1286 x += ( ( m0 + 2 ) & 4 ) << 1;
1287 x *= ( 2 - ( m0 * x ) );
1288
1289 if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
1290 if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
1291 if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
1292
1293 *mm = ~x + 1;
1294}
1295
1296/*
1297 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1298 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001299static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001300{
Paul Bakker23986e52011-04-24 08:57:21 +00001301 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001302 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001303
1304 memset( T->p, 0, T->n * ciL );
1305
1306 d = T->p;
1307 n = N->n;
1308 m = ( B->n < n ) ? B->n : n;
1309
1310 for( i = 0; i < n; i++ )
1311 {
1312 /*
1313 * T = (T + u0*B + u1*N) / 2^biL
1314 */
1315 u0 = A->p[i];
1316 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1317
1318 mpi_mul_hlp( m, B->p, d, u0 );
1319 mpi_mul_hlp( n, N->p, d, u1 );
1320
1321 *d++ = u0; d[n + 1] = 0;
1322 }
1323
1324 memcpy( A->p, d, (n + 1) * ciL );
1325
1326 if( mpi_cmp_abs( A, N ) >= 0 )
1327 mpi_sub_hlp( n, N->p, A->p );
1328 else
1329 /* prevent timing attacks */
1330 mpi_sub_hlp( n, A->p, T->p );
1331}
1332
1333/*
1334 * Montgomery reduction: A = A * R^-1 mod N
1335 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001336static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001337{
Paul Bakkera755ca12011-04-24 09:11:17 +00001338 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001339 mpi U;
1340
1341 U.n = U.s = z;
1342 U.p = &z;
1343
1344 mpi_montmul( A, &U, N, mm, T );
1345}
1346
1347/*
1348 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1349 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001350int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001351{
Paul Bakker23986e52011-04-24 08:57:21 +00001352 int ret;
1353 size_t wbits, wsize, one = 1;
1354 size_t i, j, nblimbs;
1355 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001356 t_uint ei, mm, state;
Paul Bakker5121ce52009-01-03 21:22:43 +00001357 mpi RR, T, W[64];
1358
1359 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001360 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001361
1362 /*
1363 * Init temps and window size
1364 */
1365 mpi_montg_init( &mm, N );
1366 mpi_init( &RR, &T, NULL );
1367 memset( W, 0, sizeof( W ) );
1368
1369 i = mpi_msb( E );
1370
1371 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1372 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1373
1374 j = N->n + 1;
1375 MPI_CHK( mpi_grow( X, j ) );
1376 MPI_CHK( mpi_grow( &W[1], j ) );
1377 MPI_CHK( mpi_grow( &T, j * 2 ) );
1378
1379 /*
1380 * If 1st call, pre-compute R^2 mod N
1381 */
1382 if( _RR == NULL || _RR->p == NULL )
1383 {
1384 MPI_CHK( mpi_lset( &RR, 1 ) );
1385 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1386 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1387
1388 if( _RR != NULL )
1389 memcpy( _RR, &RR, sizeof( mpi ) );
1390 }
1391 else
1392 memcpy( &RR, _RR, sizeof( mpi ) );
1393
1394 /*
1395 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1396 */
1397 if( mpi_cmp_mpi( A, N ) >= 0 )
1398 mpi_mod_mpi( &W[1], A, N );
1399 else mpi_copy( &W[1], A );
1400
1401 mpi_montmul( &W[1], &RR, N, mm, &T );
1402
1403 /*
1404 * X = R^2 * R^-1 mod N = R mod N
1405 */
1406 MPI_CHK( mpi_copy( X, &RR ) );
1407 mpi_montred( X, N, mm, &T );
1408
1409 if( wsize > 1 )
1410 {
1411 /*
1412 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1413 */
Paul Bakker23986e52011-04-24 08:57:21 +00001414 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001415
1416 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1417 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1418
1419 for( i = 0; i < wsize - 1; i++ )
1420 mpi_montmul( &W[j], &W[j], N, mm, &T );
1421
1422 /*
1423 * W[i] = W[i - 1] * W[1]
1424 */
Paul Bakker23986e52011-04-24 08:57:21 +00001425 for( i = j + 1; i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001426 {
1427 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1428 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1429
1430 mpi_montmul( &W[i], &W[1], N, mm, &T );
1431 }
1432 }
1433
1434 nblimbs = E->n;
1435 bufsize = 0;
1436 nbits = 0;
1437 wbits = 0;
1438 state = 0;
1439
1440 while( 1 )
1441 {
1442 if( bufsize == 0 )
1443 {
1444 if( nblimbs-- == 0 )
1445 break;
1446
Paul Bakkera755ca12011-04-24 09:11:17 +00001447 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001448 }
1449
1450 bufsize--;
1451
1452 ei = (E->p[nblimbs] >> bufsize) & 1;
1453
1454 /*
1455 * skip leading 0s
1456 */
1457 if( ei == 0 && state == 0 )
1458 continue;
1459
1460 if( ei == 0 && state == 1 )
1461 {
1462 /*
1463 * out of window, square X
1464 */
1465 mpi_montmul( X, X, N, mm, &T );
1466 continue;
1467 }
1468
1469 /*
1470 * add ei to current window
1471 */
1472 state = 2;
1473
1474 nbits++;
1475 wbits |= (ei << (wsize - nbits));
1476
1477 if( nbits == wsize )
1478 {
1479 /*
1480 * X = X^wsize R^-1 mod N
1481 */
1482 for( i = 0; i < wsize; i++ )
1483 mpi_montmul( X, X, N, mm, &T );
1484
1485 /*
1486 * X = X * W[wbits] R^-1 mod N
1487 */
1488 mpi_montmul( X, &W[wbits], N, mm, &T );
1489
1490 state--;
1491 nbits = 0;
1492 wbits = 0;
1493 }
1494 }
1495
1496 /*
1497 * process the remaining bits
1498 */
1499 for( i = 0; i < nbits; i++ )
1500 {
1501 mpi_montmul( X, X, N, mm, &T );
1502
1503 wbits <<= 1;
1504
Paul Bakker23986e52011-04-24 08:57:21 +00001505 if( (wbits & (one << wsize)) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001506 mpi_montmul( X, &W[1], N, mm, &T );
1507 }
1508
1509 /*
1510 * X = A^E * R * R^-1 mod N = A^E mod N
1511 */
1512 mpi_montred( X, N, mm, &T );
1513
1514cleanup:
1515
Paul Bakker23986e52011-04-24 08:57:21 +00001516 for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001517 mpi_free( &W[i], NULL );
1518
1519 if( _RR != NULL )
1520 mpi_free( &W[1], &T, NULL );
1521 else mpi_free( &W[1], &T, &RR, NULL );
1522
1523 return( ret );
1524}
1525
Paul Bakker5121ce52009-01-03 21:22:43 +00001526/*
1527 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1528 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001529int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001530{
Paul Bakker23986e52011-04-24 08:57:21 +00001531 int ret;
1532 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001533 mpi TG, TA, TB;
1534
1535 mpi_init( &TG, &TA, &TB, NULL );
1536
Paul Bakker5121ce52009-01-03 21:22:43 +00001537 MPI_CHK( mpi_copy( &TA, A ) );
1538 MPI_CHK( mpi_copy( &TB, B ) );
1539
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001540 lz = mpi_lsb( &TA );
1541 lzt = mpi_lsb( &TB );
1542
1543 if ( lzt < lz )
1544 lz = lzt;
1545
1546 MPI_CHK( mpi_shift_r( &TA, lz ) );
1547 MPI_CHK( mpi_shift_r( &TB, lz ) );
1548
Paul Bakker5121ce52009-01-03 21:22:43 +00001549 TA.s = TB.s = 1;
1550
1551 while( mpi_cmp_int( &TA, 0 ) != 0 )
1552 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001553 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1554 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001555
1556 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1557 {
1558 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1559 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1560 }
1561 else
1562 {
1563 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1564 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1565 }
1566 }
1567
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001568 MPI_CHK( mpi_shift_l( &TB, lz ) );
1569 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001570
1571cleanup:
1572
1573 mpi_free( &TB, &TA, &TG, NULL );
1574
1575 return( ret );
1576}
1577
Paul Bakker23986e52011-04-24 08:57:21 +00001578int mpi_fill_random( mpi *X, size_t size, int (*f_rng)(void *), void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001579{
Paul Bakker23986e52011-04-24 08:57:21 +00001580 int ret;
1581 size_t k;
Paul Bakker287781a2011-03-26 13:18:49 +00001582 unsigned char *p;
1583
1584 MPI_CHK( mpi_grow( X, size ) );
1585 MPI_CHK( mpi_lset( X, 0 ) );
1586
1587 p = (unsigned char *) X->p;
1588 for( k = 0; k < X->n * ciL; k++ )
1589 *p++ = (unsigned char) f_rng( p_rng );
1590
1591cleanup:
1592 return( ret );
1593}
1594
Paul Bakker70b3eed2009-03-14 18:01:25 +00001595#if defined(POLARSSL_GENPRIME)
1596
Paul Bakker5121ce52009-01-03 21:22:43 +00001597/*
1598 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1599 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001600int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001601{
1602 int ret;
1603 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1604
1605 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001606 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001607
1608 mpi_init( &TA, &TU, &U1, &U2, &G,
1609 &TB, &TV, &V1, &V2, NULL );
1610
1611 MPI_CHK( mpi_gcd( &G, A, N ) );
1612
1613 if( mpi_cmp_int( &G, 1 ) != 0 )
1614 {
Paul Bakker40e46942009-01-03 21:51:57 +00001615 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001616 goto cleanup;
1617 }
1618
1619 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1620 MPI_CHK( mpi_copy( &TU, &TA ) );
1621 MPI_CHK( mpi_copy( &TB, N ) );
1622 MPI_CHK( mpi_copy( &TV, N ) );
1623
1624 MPI_CHK( mpi_lset( &U1, 1 ) );
1625 MPI_CHK( mpi_lset( &U2, 0 ) );
1626 MPI_CHK( mpi_lset( &V1, 0 ) );
1627 MPI_CHK( mpi_lset( &V2, 1 ) );
1628
1629 do
1630 {
1631 while( ( TU.p[0] & 1 ) == 0 )
1632 {
1633 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1634
1635 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1636 {
1637 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1638 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1639 }
1640
1641 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1642 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1643 }
1644
1645 while( ( TV.p[0] & 1 ) == 0 )
1646 {
1647 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1648
1649 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1650 {
1651 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1652 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1653 }
1654
1655 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1656 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1657 }
1658
1659 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1660 {
1661 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1662 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1663 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1664 }
1665 else
1666 {
1667 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1668 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1669 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1670 }
1671 }
1672 while( mpi_cmp_int( &TU, 0 ) != 0 );
1673
1674 while( mpi_cmp_int( &V1, 0 ) < 0 )
1675 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1676
1677 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1678 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1679
1680 MPI_CHK( mpi_copy( X, &V1 ) );
1681
1682cleanup:
1683
1684 mpi_free( &V2, &V1, &TV, &TB, &G,
1685 &U2, &U1, &TU, &TA, NULL );
1686
1687 return( ret );
1688}
1689
1690static const int small_prime[] =
1691{
1692 3, 5, 7, 11, 13, 17, 19, 23,
1693 29, 31, 37, 41, 43, 47, 53, 59,
1694 61, 67, 71, 73, 79, 83, 89, 97,
1695 101, 103, 107, 109, 113, 127, 131, 137,
1696 139, 149, 151, 157, 163, 167, 173, 179,
1697 181, 191, 193, 197, 199, 211, 223, 227,
1698 229, 233, 239, 241, 251, 257, 263, 269,
1699 271, 277, 281, 283, 293, 307, 311, 313,
1700 317, 331, 337, 347, 349, 353, 359, 367,
1701 373, 379, 383, 389, 397, 401, 409, 419,
1702 421, 431, 433, 439, 443, 449, 457, 461,
1703 463, 467, 479, 487, 491, 499, 503, 509,
1704 521, 523, 541, 547, 557, 563, 569, 571,
1705 577, 587, 593, 599, 601, 607, 613, 617,
1706 619, 631, 641, 643, 647, 653, 659, 661,
1707 673, 677, 683, 691, 701, 709, 719, 727,
1708 733, 739, 743, 751, 757, 761, 769, 773,
1709 787, 797, 809, 811, 821, 823, 827, 829,
1710 839, 853, 857, 859, 863, 877, 881, 883,
1711 887, 907, 911, 919, 929, 937, 941, 947,
1712 953, 967, 971, 977, 983, 991, 997, -103
1713};
1714
1715/*
1716 * Miller-Rabin primality test (HAC 4.24)
1717 */
1718int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng )
1719{
Paul Bakker23986e52011-04-24 08:57:21 +00001720 int ret, xs;
1721 size_t i, j, n, s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001722 mpi W, R, T, A, RR;
Paul Bakker5121ce52009-01-03 21:22:43 +00001723
Paul Bakker48eab262009-06-25 21:25:49 +00001724 if( mpi_cmp_int( X, 0 ) == 0 ||
1725 mpi_cmp_int( X, 1 ) == 0 )
1726 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1727
1728 if( mpi_cmp_int( X, 2 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001729 return( 0 );
1730
1731 mpi_init( &W, &R, &T, &A, &RR, NULL );
1732
1733 xs = X->s; X->s = 1;
1734
1735 /*
1736 * test trivial factors first
1737 */
1738 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001739 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001740
1741 for( i = 0; small_prime[i] > 0; i++ )
1742 {
Paul Bakkera755ca12011-04-24 09:11:17 +00001743 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001744
1745 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
1746 return( 0 );
1747
1748 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1749
1750 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001751 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001752 }
1753
1754 /*
1755 * W = |X| - 1
1756 * R = W >> lsb( W )
1757 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001758 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001759 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001760 MPI_CHK( mpi_copy( &R, &W ) );
1761 MPI_CHK( mpi_shift_r( &R, s ) );
1762
1763 i = mpi_msb( X );
1764 /*
1765 * HAC, table 4.4
1766 */
1767 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1768 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1769 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1770
1771 for( i = 0; i < n; i++ )
1772 {
1773 /*
1774 * pick a random A, 1 < A < |X| - 1
1775 */
Paul Bakker287781a2011-03-26 13:18:49 +00001776 mpi_fill_random( &A, X->n, f_rng, p_rng );
Paul Bakker5121ce52009-01-03 21:22:43 +00001777
Paul Bakkerb94081b2011-01-05 15:53:06 +00001778 if( mpi_cmp_mpi( &A, &W ) >= 0 )
1779 {
1780 j = mpi_msb( &A ) - mpi_msb( &W );
1781 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1782 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001783 A.p[0] |= 3;
1784
1785 /*
1786 * A = A^R mod |X|
1787 */
1788 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1789
1790 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1791 mpi_cmp_int( &A, 1 ) == 0 )
1792 continue;
1793
1794 j = 1;
1795 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1796 {
1797 /*
1798 * A = A * A mod |X|
1799 */
1800 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1801 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1802
1803 if( mpi_cmp_int( &A, 1 ) == 0 )
1804 break;
1805
1806 j++;
1807 }
1808
1809 /*
1810 * not prime if A != |X| - 1 or A == 1
1811 */
1812 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1813 mpi_cmp_int( &A, 1 ) == 0 )
1814 {
Paul Bakker40e46942009-01-03 21:51:57 +00001815 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001816 break;
1817 }
1818 }
1819
1820cleanup:
1821
1822 X->s = xs;
1823
1824 mpi_free( &RR, &A, &T, &R, &W, NULL );
1825
1826 return( ret );
1827}
1828
1829/*
1830 * Prime number generation
1831 */
Paul Bakker23986e52011-04-24 08:57:21 +00001832int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakker5121ce52009-01-03 21:22:43 +00001833 int (*f_rng)(void *), void *p_rng )
1834{
Paul Bakker23986e52011-04-24 08:57:21 +00001835 int ret;
1836 size_t k, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001837 mpi Y;
1838
Paul Bakkerf9688572011-05-05 10:00:45 +00001839 if( nbits < 3 || nbits > 4096 )
Paul Bakker40e46942009-01-03 21:51:57 +00001840 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001841
1842 mpi_init( &Y, NULL );
1843
1844 n = BITS_TO_LIMBS( nbits );
1845
Paul Bakker287781a2011-03-26 13:18:49 +00001846 mpi_fill_random( X, n, f_rng, p_rng );
Paul Bakker5121ce52009-01-03 21:22:43 +00001847
1848 k = mpi_msb( X );
1849 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
1850 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
1851
1852 X->p[0] |= 3;
1853
1854 if( dh_flag == 0 )
1855 {
1856 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
1857 {
Paul Bakker40e46942009-01-03 21:51:57 +00001858 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001859 goto cleanup;
1860
1861 MPI_CHK( mpi_add_int( X, X, 2 ) );
1862 }
1863 }
1864 else
1865 {
1866 MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
1867 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1868
1869 while( 1 )
1870 {
1871 if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
1872 {
1873 if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
1874 break;
1875
Paul Bakker40e46942009-01-03 21:51:57 +00001876 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001877 goto cleanup;
1878 }
1879
Paul Bakker40e46942009-01-03 21:51:57 +00001880 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001881 goto cleanup;
1882
1883 MPI_CHK( mpi_add_int( &Y, X, 1 ) );
1884 MPI_CHK( mpi_add_int( X, X, 2 ) );
1885 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1886 }
1887 }
1888
1889cleanup:
1890
1891 mpi_free( &Y, NULL );
1892
1893 return( ret );
1894}
1895
1896#endif
1897
Paul Bakker40e46942009-01-03 21:51:57 +00001898#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00001899
Paul Bakker23986e52011-04-24 08:57:21 +00001900#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001901
1902static const int gcd_pairs[GCD_PAIR_COUNT][3] =
1903{
1904 { 693, 609, 21 },
1905 { 1764, 868, 28 },
1906 { 768454923, 542167814, 1 }
1907};
1908
Paul Bakker5121ce52009-01-03 21:22:43 +00001909/*
1910 * Checkup routine
1911 */
1912int mpi_self_test( int verbose )
1913{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001914 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001915 mpi A, E, N, X, Y, U, V;
1916
1917 mpi_init( &A, &E, &N, &X, &Y, &U, &V, NULL );
1918
1919 MPI_CHK( mpi_read_string( &A, 16,
1920 "EFE021C2645FD1DC586E69184AF4A31E" \
1921 "D5F53E93B5F123FA41680867BA110131" \
1922 "944FE7952E2517337780CB0DB80E61AA" \
1923 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
1924
1925 MPI_CHK( mpi_read_string( &E, 16,
1926 "B2E7EFD37075B9F03FF989C7C5051C20" \
1927 "34D2A323810251127E7BF8625A4F49A5" \
1928 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
1929 "5B5C25763222FEFCCFC38B832366C29E" ) );
1930
1931 MPI_CHK( mpi_read_string( &N, 16,
1932 "0066A198186C18C10B2F5ED9B522752A" \
1933 "9830B69916E535C8F047518A889A43A5" \
1934 "94B6BED27A168D31D4A52F88925AA8F5" ) );
1935
1936 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
1937
1938 MPI_CHK( mpi_read_string( &U, 16,
1939 "602AB7ECA597A3D6B56FF9829A5E8B85" \
1940 "9E857EA95A03512E2BAE7391688D264A" \
1941 "A5663B0341DB9CCFD2C4C5F421FEC814" \
1942 "8001B72E848A38CAE1C65F78E56ABDEF" \
1943 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
1944 "ECF677152EF804370C1A305CAF3B5BF1" \
1945 "30879B56C61DE584A0F53A2447A51E" ) );
1946
1947 if( verbose != 0 )
1948 printf( " MPI test #1 (mul_mpi): " );
1949
1950 if( mpi_cmp_mpi( &X, &U ) != 0 )
1951 {
1952 if( verbose != 0 )
1953 printf( "failed\n" );
1954
1955 return( 1 );
1956 }
1957
1958 if( verbose != 0 )
1959 printf( "passed\n" );
1960
1961 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
1962
1963 MPI_CHK( mpi_read_string( &U, 16,
1964 "256567336059E52CAE22925474705F39A94" ) );
1965
1966 MPI_CHK( mpi_read_string( &V, 16,
1967 "6613F26162223DF488E9CD48CC132C7A" \
1968 "0AC93C701B001B092E4E5B9F73BCD27B" \
1969 "9EE50D0657C77F374E903CDFA4C642" ) );
1970
1971 if( verbose != 0 )
1972 printf( " MPI test #2 (div_mpi): " );
1973
1974 if( mpi_cmp_mpi( &X, &U ) != 0 ||
1975 mpi_cmp_mpi( &Y, &V ) != 0 )
1976 {
1977 if( verbose != 0 )
1978 printf( "failed\n" );
1979
1980 return( 1 );
1981 }
1982
1983 if( verbose != 0 )
1984 printf( "passed\n" );
1985
1986 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
1987
1988 MPI_CHK( mpi_read_string( &U, 16,
1989 "36E139AEA55215609D2816998ED020BB" \
1990 "BD96C37890F65171D948E9BC7CBAA4D9" \
1991 "325D24D6A3C12710F10A09FA08AB87" ) );
1992
1993 if( verbose != 0 )
1994 printf( " MPI test #3 (exp_mod): " );
1995
1996 if( mpi_cmp_mpi( &X, &U ) != 0 )
1997 {
1998 if( verbose != 0 )
1999 printf( "failed\n" );
2000
2001 return( 1 );
2002 }
2003
2004 if( verbose != 0 )
2005 printf( "passed\n" );
2006
2007 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2008
2009 MPI_CHK( mpi_read_string( &U, 16,
2010 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2011 "C3DBA76456363A10869622EAC2DD84EC" \
2012 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2013
2014 if( verbose != 0 )
2015 printf( " MPI test #4 (inv_mod): " );
2016
2017 if( mpi_cmp_mpi( &X, &U ) != 0 )
2018 {
2019 if( verbose != 0 )
2020 printf( "failed\n" );
2021
2022 return( 1 );
2023 }
2024
2025 if( verbose != 0 )
2026 printf( "passed\n" );
2027
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002028 if( verbose != 0 )
2029 printf( " MPI test #5 (simple gcd): " );
2030
2031 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2032 {
2033 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002034 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002035
Paul Bakker23986e52011-04-24 08:57:21 +00002036 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002037
Paul Bakker23986e52011-04-24 08:57:21 +00002038 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2039 {
2040 if( verbose != 0 )
2041 printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002042
Paul Bakker23986e52011-04-24 08:57:21 +00002043 return( 1 );
2044 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002045 }
2046
2047 if( verbose != 0 )
2048 printf( "passed\n" );
2049
Paul Bakker5121ce52009-01-03 21:22:43 +00002050cleanup:
2051
2052 if( ret != 0 && verbose != 0 )
2053 printf( "Unexpected error, return code = %08X\n", ret );
2054
2055 mpi_free( &V, &U, &Y, &X, &N, &E, &A, NULL );
2056
2057 if( verbose != 0 )
2058 printf( "\n" );
2059
2060 return( ret );
2061}
2062
2063#endif
2064
2065#endif