blob: 36e78e165d0b262449f3f3876a04e734be01488c [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 )
92 return( 1 );
93
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 Bakker5121ce52009-01-03 21:22:43 +000097 return( 1 );
98
99 memset( p, 0, nblimbs * ciL );
100
101 if( X->p != NULL )
102 {
103 memcpy( p, X->p, X->n * ciL );
104 memset( X->p, 0, X->n * ciL );
105 free( X->p );
106 }
107
108 X->n = nblimbs;
109 X->p = p;
110 }
111
112 return( 0 );
113}
114
115/*
116 * Copy the contents of Y into X
117 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000118int mpi_copy( mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000119{
Paul Bakker23986e52011-04-24 08:57:21 +0000120 int ret;
121 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000122
123 if( X == Y )
124 return( 0 );
125
126 for( i = Y->n - 1; i > 0; i-- )
127 if( Y->p[i] != 0 )
128 break;
129 i++;
130
131 X->s = Y->s;
132
133 MPI_CHK( mpi_grow( X, i ) );
134
135 memset( X->p, 0, X->n * ciL );
136 memcpy( X->p, Y->p, i * ciL );
137
138cleanup:
139
140 return( ret );
141}
142
143/*
144 * Swap the contents of X and Y
145 */
146void mpi_swap( mpi *X, mpi *Y )
147{
148 mpi T;
149
150 memcpy( &T, X, sizeof( mpi ) );
151 memcpy( X, Y, sizeof( mpi ) );
152 memcpy( Y, &T, sizeof( mpi ) );
153}
154
155/*
156 * Set value from integer
157 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000158int mpi_lset( mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000159{
160 int ret;
161
162 MPI_CHK( mpi_grow( X, 1 ) );
163 memset( X->p, 0, X->n * ciL );
164
165 X->p[0] = ( z < 0 ) ? -z : z;
166 X->s = ( z < 0 ) ? -1 : 1;
167
168cleanup:
169
170 return( ret );
171}
172
173/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000174 * Get a specific bit
175 */
176int mpi_get_bit( mpi *X, size_t pos )
177{
178 if( X->n * biL <= pos )
179 return( 0 );
180
181 return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
182}
183
184/*
185 * Set a bit to a specific value of 0 or 1
186 */
187int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
188{
189 int ret = 0;
190 size_t off = pos / biL;
191 size_t idx = pos % biL;
192
193 if( val != 0 && val != 1 )
194 return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
195
196 if( X->n * biL <= pos )
197 {
198 if( val == 0 )
199 return ( 0 );
200
201 MPI_CHK( mpi_grow( X, off + 1 ) );
202 }
203
204 X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
205
206cleanup:
207
208 return( ret );
209}
210
211/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000212 * Return the number of least significant bits
213 */
Paul Bakker23986e52011-04-24 08:57:21 +0000214size_t mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000215{
Paul Bakker23986e52011-04-24 08:57:21 +0000216 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000217
218 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000219 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000220 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
221 return( count );
222
223 return( 0 );
224}
225
226/*
227 * Return the number of most significant bits
228 */
Paul Bakker23986e52011-04-24 08:57:21 +0000229size_t mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000230{
Paul Bakker23986e52011-04-24 08:57:21 +0000231 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000232
233 for( i = X->n - 1; i > 0; i-- )
234 if( X->p[i] != 0 )
235 break;
236
Paul Bakker23986e52011-04-24 08:57:21 +0000237 for( j = biL; j > 0; j-- )
238 if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000239 break;
240
Paul Bakker23986e52011-04-24 08:57:21 +0000241 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000242}
243
244/*
245 * Return the total size in bytes
246 */
Paul Bakker23986e52011-04-24 08:57:21 +0000247size_t mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000248{
249 return( ( mpi_msb( X ) + 7 ) >> 3 );
250}
251
252/*
253 * Convert an ASCII character to digit value
254 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000255static int mpi_get_digit( t_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000256{
257 *d = 255;
258
259 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
260 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
261 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
262
Paul Bakkera755ca12011-04-24 09:11:17 +0000263 if( *d >= (t_uint) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000264 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000265
266 return( 0 );
267}
268
269/*
270 * Import from an ASCII string
271 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000272int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000273{
Paul Bakker23986e52011-04-24 08:57:21 +0000274 int ret;
275 size_t i, j, slen, n;
Paul Bakkera755ca12011-04-24 09:11:17 +0000276 t_uint d;
Paul Bakker5121ce52009-01-03 21:22:43 +0000277 mpi T;
278
279 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000280 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000281
Paul Bakker6c591fa2011-05-05 11:49:20 +0000282 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000283
Paul Bakkerff60ee62010-03-16 21:09:09 +0000284 slen = strlen( s );
285
Paul Bakker5121ce52009-01-03 21:22:43 +0000286 if( radix == 16 )
287 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000288 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000289
290 MPI_CHK( mpi_grow( X, n ) );
291 MPI_CHK( mpi_lset( X, 0 ) );
292
Paul Bakker23986e52011-04-24 08:57:21 +0000293 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000294 {
Paul Bakker23986e52011-04-24 08:57:21 +0000295 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000296 {
297 X->s = -1;
298 break;
299 }
300
Paul Bakker23986e52011-04-24 08:57:21 +0000301 MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000302 X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
303 }
304 }
305 else
306 {
307 MPI_CHK( mpi_lset( X, 0 ) );
308
Paul Bakkerff60ee62010-03-16 21:09:09 +0000309 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000310 {
311 if( i == 0 && s[i] == '-' )
312 {
313 X->s = -1;
314 continue;
315 }
316
317 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
318 MPI_CHK( mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000319
320 if( X->s == 1 )
321 {
322 MPI_CHK( mpi_add_int( X, &T, d ) );
323 }
324 else
325 {
326 MPI_CHK( mpi_sub_int( X, &T, d ) );
327 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000328 }
329 }
330
331cleanup:
332
Paul Bakker6c591fa2011-05-05 11:49:20 +0000333 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000334
335 return( ret );
336}
337
338/*
339 * Helper to write the digits high-order first
340 */
341static int mpi_write_hlp( mpi *X, int radix, char **p )
342{
343 int ret;
Paul Bakkera755ca12011-04-24 09:11:17 +0000344 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000345
346 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000347 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000348
349 MPI_CHK( mpi_mod_int( &r, X, radix ) );
350 MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
351
352 if( mpi_cmp_int( X, 0 ) != 0 )
353 MPI_CHK( mpi_write_hlp( X, radix, p ) );
354
355 if( r < 10 )
356 *(*p)++ = (char)( r + 0x30 );
357 else
358 *(*p)++ = (char)( r + 0x37 );
359
360cleanup:
361
362 return( ret );
363}
364
365/*
366 * Export into an ASCII string
367 */
Paul Bakker23986e52011-04-24 08:57:21 +0000368int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000369{
Paul Bakker23986e52011-04-24 08:57:21 +0000370 int ret = 0;
371 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000372 char *p;
373 mpi T;
374
375 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000376 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000377
378 n = mpi_msb( X );
379 if( radix >= 4 ) n >>= 1;
380 if( radix >= 16 ) n >>= 1;
381 n += 3;
382
383 if( *slen < n )
384 {
385 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000386 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 }
388
389 p = s;
Paul Bakker6c591fa2011-05-05 11:49:20 +0000390 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000391
392 if( X->s == -1 )
393 *p++ = '-';
394
395 if( radix == 16 )
396 {
Paul Bakker23986e52011-04-24 08:57:21 +0000397 int c;
398 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000399
Paul Bakker23986e52011-04-24 08:57:21 +0000400 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000401 {
Paul Bakker23986e52011-04-24 08:57:21 +0000402 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000403 {
Paul Bakker23986e52011-04-24 08:57:21 +0000404 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000405
Paul Bakker23986e52011-04-24 08:57:21 +0000406 if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000407 continue;
408
409 p += sprintf( p, "%02X", c );
410 k = 1;
411 }
412 }
413 }
414 else
415 {
416 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000417
418 if( T.s == -1 )
419 T.s = 1;
420
Paul Bakker5121ce52009-01-03 21:22:43 +0000421 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
422 }
423
424 *p++ = '\0';
425 *slen = p - s;
426
427cleanup:
428
Paul Bakker6c591fa2011-05-05 11:49:20 +0000429 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000430
431 return( ret );
432}
433
Paul Bakker335db3f2011-04-25 15:28:35 +0000434#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000435/*
436 * Read X from an opened file
437 */
438int mpi_read_file( mpi *X, int radix, FILE *fin )
439{
Paul Bakkera755ca12011-04-24 09:11:17 +0000440 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000441 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000442 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000443 /*
444 * Buffer should have space for (short) label and hexified MPI and '\0'
445 */
446 char s[ 2 * POLARSSL_MPI_MAX_SIZE + 10 ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000447
448 memset( s, 0, sizeof( s ) );
449 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000450 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000451
452 slen = strlen( s );
453 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
454 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
455
456 p = s + slen;
457 while( --p >= s )
458 if( mpi_get_digit( &d, radix, *p ) != 0 )
459 break;
460
461 return( mpi_read_string( X, radix, p + 1 ) );
462}
463
464/*
465 * Write X into an opened file (or stdout if fout == NULL)
466 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000467int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000468{
Paul Bakker23986e52011-04-24 08:57:21 +0000469 int ret;
470 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000471 /*
472 * Buffer should have space for minus sign, hexified MPI and '\0'
473 */
474 char s[ 2 * POLARSSL_MPI_MAX_SIZE + 2 ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000475
476 n = sizeof( s );
477 memset( s, 0, n );
478 n -= 2;
479
Paul Bakker23986e52011-04-24 08:57:21 +0000480 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000481
482 if( p == NULL ) p = "";
483
484 plen = strlen( p );
485 slen = strlen( s );
486 s[slen++] = '\r';
487 s[slen++] = '\n';
488
489 if( fout != NULL )
490 {
491 if( fwrite( p, 1, plen, fout ) != plen ||
492 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000493 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494 }
495 else
496 printf( "%s%s", p, s );
497
498cleanup:
499
500 return( ret );
501}
Paul Bakker335db3f2011-04-25 15:28:35 +0000502#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000503
504/*
505 * Import X from unsigned binary data, big endian
506 */
Paul Bakker23986e52011-04-24 08:57:21 +0000507int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000508{
Paul Bakker23986e52011-04-24 08:57:21 +0000509 int ret;
510 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000511
512 for( n = 0; n < buflen; n++ )
513 if( buf[n] != 0 )
514 break;
515
516 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
517 MPI_CHK( mpi_lset( X, 0 ) );
518
Paul Bakker23986e52011-04-24 08:57:21 +0000519 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000520 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000521
522cleanup:
523
524 return( ret );
525}
526
527/*
528 * Export X into unsigned binary data, big endian
529 */
Paul Bakker23986e52011-04-24 08:57:21 +0000530int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000531{
Paul Bakker23986e52011-04-24 08:57:21 +0000532 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000533
534 n = mpi_size( X );
535
536 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000537 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000538
539 memset( buf, 0, buflen );
540
541 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
542 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
543
544 return( 0 );
545}
546
547/*
548 * Left-shift: X <<= count
549 */
Paul Bakker23986e52011-04-24 08:57:21 +0000550int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000551{
Paul Bakker23986e52011-04-24 08:57:21 +0000552 int ret;
553 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000554 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000555
556 v0 = count / (biL );
557 t1 = count & (biL - 1);
558
559 i = mpi_msb( X ) + count;
560
Paul Bakkerf9688572011-05-05 10:00:45 +0000561 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000562 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
563
564 ret = 0;
565
566 /*
567 * shift by count / limb_size
568 */
569 if( v0 > 0 )
570 {
Paul Bakker23986e52011-04-24 08:57:21 +0000571 for( i = X->n; i > v0; i-- )
572 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000573
Paul Bakker23986e52011-04-24 08:57:21 +0000574 for( ; i > 0; i-- )
575 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000576 }
577
578 /*
579 * shift by count % limb_size
580 */
581 if( t1 > 0 )
582 {
583 for( i = v0; i < X->n; i++ )
584 {
585 r1 = X->p[i] >> (biL - t1);
586 X->p[i] <<= t1;
587 X->p[i] |= r0;
588 r0 = r1;
589 }
590 }
591
592cleanup:
593
594 return( ret );
595}
596
597/*
598 * Right-shift: X >>= count
599 */
Paul Bakker23986e52011-04-24 08:57:21 +0000600int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000601{
Paul Bakker23986e52011-04-24 08:57:21 +0000602 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000603 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000604
605 v0 = count / biL;
606 v1 = count & (biL - 1);
607
608 /*
609 * shift by count / limb_size
610 */
611 if( v0 > 0 )
612 {
613 for( i = 0; i < X->n - v0; i++ )
614 X->p[i] = X->p[i + v0];
615
616 for( ; i < X->n; i++ )
617 X->p[i] = 0;
618 }
619
620 /*
621 * shift by count % limb_size
622 */
623 if( v1 > 0 )
624 {
Paul Bakker23986e52011-04-24 08:57:21 +0000625 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000626 {
Paul Bakker23986e52011-04-24 08:57:21 +0000627 r1 = X->p[i - 1] << (biL - v1);
628 X->p[i - 1] >>= v1;
629 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000630 r0 = r1;
631 }
632 }
633
634 return( 0 );
635}
636
637/*
638 * Compare unsigned values
639 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000640int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000641{
Paul Bakker23986e52011-04-24 08:57:21 +0000642 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000643
Paul Bakker23986e52011-04-24 08:57:21 +0000644 for( i = X->n; i > 0; i-- )
645 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000646 break;
647
Paul Bakker23986e52011-04-24 08:57:21 +0000648 for( j = Y->n; j > 0; j-- )
649 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000650 break;
651
Paul Bakker23986e52011-04-24 08:57:21 +0000652 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000653 return( 0 );
654
655 if( i > j ) return( 1 );
656 if( j > i ) return( -1 );
657
Paul Bakker23986e52011-04-24 08:57:21 +0000658 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000659 {
Paul Bakker23986e52011-04-24 08:57:21 +0000660 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
661 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000662 }
663
664 return( 0 );
665}
666
667/*
668 * Compare signed values
669 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000670int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000671{
Paul Bakker23986e52011-04-24 08:57:21 +0000672 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000673
Paul Bakker23986e52011-04-24 08:57:21 +0000674 for( i = X->n; i > 0; i-- )
675 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000676 break;
677
Paul Bakker23986e52011-04-24 08:57:21 +0000678 for( j = Y->n; j > 0; j-- )
679 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000680 break;
681
Paul Bakker23986e52011-04-24 08:57:21 +0000682 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000683 return( 0 );
684
685 if( i > j ) return( X->s );
686 if( j > i ) return( -X->s );
687
688 if( X->s > 0 && Y->s < 0 ) return( 1 );
689 if( Y->s > 0 && X->s < 0 ) return( -1 );
690
Paul Bakker23986e52011-04-24 08:57:21 +0000691 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000692 {
Paul Bakker23986e52011-04-24 08:57:21 +0000693 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
694 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000695 }
696
697 return( 0 );
698}
699
700/*
701 * Compare signed values
702 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000703int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000704{
705 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000706 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
708 *p = ( z < 0 ) ? -z : z;
709 Y.s = ( z < 0 ) ? -1 : 1;
710 Y.n = 1;
711 Y.p = p;
712
713 return( mpi_cmp_mpi( X, &Y ) );
714}
715
716/*
717 * Unsigned addition: X = |A| + |B| (HAC 14.7)
718 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000719int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000720{
Paul Bakker23986e52011-04-24 08:57:21 +0000721 int ret;
722 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000723 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000724
725 if( X == B )
726 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000727 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000728 }
729
730 if( X != A )
731 MPI_CHK( mpi_copy( X, A ) );
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000732
733 /*
734 * X should always be positive as a result of unsigned additions.
735 */
736 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000737
Paul Bakker23986e52011-04-24 08:57:21 +0000738 for( j = B->n; j > 0; j-- )
739 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000740 break;
741
Paul Bakker23986e52011-04-24 08:57:21 +0000742 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000743
744 o = B->p; p = X->p; c = 0;
745
Paul Bakker23986e52011-04-24 08:57:21 +0000746 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000747 {
748 *p += c; c = ( *p < c );
749 *p += *o; c += ( *p < *o );
750 }
751
752 while( c != 0 )
753 {
754 if( i >= X->n )
755 {
756 MPI_CHK( mpi_grow( X, i + 1 ) );
757 p = X->p + i;
758 }
759
760 *p += c; c = ( *p < c ); i++;
761 }
762
763cleanup:
764
765 return( ret );
766}
767
768/*
769 * Helper for mpi substraction
770 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000771static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000772{
Paul Bakker23986e52011-04-24 08:57:21 +0000773 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000774 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000775
776 for( i = c = 0; i < n; i++, s++, d++ )
777 {
778 z = ( *d < c ); *d -= c;
779 c = ( *d < *s ) + z; *d -= *s;
780 }
781
782 while( c != 0 )
783 {
784 z = ( *d < c ); *d -= c;
785 c = z; i++; d++;
786 }
787}
788
789/*
790 * Unsigned substraction: X = |A| - |B| (HAC 14.9)
791 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000792int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000793{
794 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000795 int ret;
796 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000797
798 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000799 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000800
Paul Bakker6c591fa2011-05-05 11:49:20 +0000801 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000802
803 if( X == B )
804 {
805 MPI_CHK( mpi_copy( &TB, B ) );
806 B = &TB;
807 }
808
809 if( X != A )
810 MPI_CHK( mpi_copy( X, A ) );
811
Paul Bakker1ef7a532009-06-20 10:50:55 +0000812 /*
813 * X should always be positive as a result of unsigned substractions.
814 */
815 X->s = 1;
816
Paul Bakker5121ce52009-01-03 21:22:43 +0000817 ret = 0;
818
Paul Bakker23986e52011-04-24 08:57:21 +0000819 for( n = B->n; n > 0; n-- )
820 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000821 break;
822
Paul Bakker23986e52011-04-24 08:57:21 +0000823 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000824
825cleanup:
826
Paul Bakker6c591fa2011-05-05 11:49:20 +0000827 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000828
829 return( ret );
830}
831
832/*
833 * Signed addition: X = A + B
834 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000835int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000836{
837 int ret, s = A->s;
838
839 if( A->s * B->s < 0 )
840 {
841 if( mpi_cmp_abs( A, B ) >= 0 )
842 {
843 MPI_CHK( mpi_sub_abs( X, A, B ) );
844 X->s = s;
845 }
846 else
847 {
848 MPI_CHK( mpi_sub_abs( X, B, A ) );
849 X->s = -s;
850 }
851 }
852 else
853 {
854 MPI_CHK( mpi_add_abs( X, A, B ) );
855 X->s = s;
856 }
857
858cleanup:
859
860 return( ret );
861}
862
863/*
864 * Signed substraction: X = A - B
865 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000866int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000867{
868 int ret, s = A->s;
869
870 if( A->s * B->s > 0 )
871 {
872 if( mpi_cmp_abs( A, B ) >= 0 )
873 {
874 MPI_CHK( mpi_sub_abs( X, A, B ) );
875 X->s = s;
876 }
877 else
878 {
879 MPI_CHK( mpi_sub_abs( X, B, A ) );
880 X->s = -s;
881 }
882 }
883 else
884 {
885 MPI_CHK( mpi_add_abs( X, A, B ) );
886 X->s = s;
887 }
888
889cleanup:
890
891 return( ret );
892}
893
894/*
895 * Signed addition: X = A + b
896 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000897int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000898{
899 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000900 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000901
902 p[0] = ( b < 0 ) ? -b : b;
903 _B.s = ( b < 0 ) ? -1 : 1;
904 _B.n = 1;
905 _B.p = p;
906
907 return( mpi_add_mpi( X, A, &_B ) );
908}
909
910/*
911 * Signed substraction: X = A - b
912 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000913int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000914{
915 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000916 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000917
918 p[0] = ( b < 0 ) ? -b : b;
919 _B.s = ( b < 0 ) ? -1 : 1;
920 _B.n = 1;
921 _B.p = p;
922
923 return( mpi_sub_mpi( X, A, &_B ) );
924}
925
926/*
927 * Helper for mpi multiplication
928 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000929static void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000930{
Paul Bakkera755ca12011-04-24 09:11:17 +0000931 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000932
933#if defined(MULADDC_HUIT)
934 for( ; i >= 8; i -= 8 )
935 {
936 MULADDC_INIT
937 MULADDC_HUIT
938 MULADDC_STOP
939 }
940
941 for( ; i > 0; i-- )
942 {
943 MULADDC_INIT
944 MULADDC_CORE
945 MULADDC_STOP
946 }
947#else
948 for( ; i >= 16; i -= 16 )
949 {
950 MULADDC_INIT
951 MULADDC_CORE MULADDC_CORE
952 MULADDC_CORE MULADDC_CORE
953 MULADDC_CORE MULADDC_CORE
954 MULADDC_CORE MULADDC_CORE
955
956 MULADDC_CORE MULADDC_CORE
957 MULADDC_CORE MULADDC_CORE
958 MULADDC_CORE MULADDC_CORE
959 MULADDC_CORE MULADDC_CORE
960 MULADDC_STOP
961 }
962
963 for( ; i >= 8; i -= 8 )
964 {
965 MULADDC_INIT
966 MULADDC_CORE MULADDC_CORE
967 MULADDC_CORE MULADDC_CORE
968
969 MULADDC_CORE MULADDC_CORE
970 MULADDC_CORE MULADDC_CORE
971 MULADDC_STOP
972 }
973
974 for( ; i > 0; i-- )
975 {
976 MULADDC_INIT
977 MULADDC_CORE
978 MULADDC_STOP
979 }
980#endif
981
982 t++;
983
984 do {
985 *d += c; c = ( *d < c ); d++;
986 }
987 while( c != 0 );
988}
989
990/*
991 * Baseline multiplication: X = A * B (HAC 14.12)
992 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000993int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000994{
Paul Bakker23986e52011-04-24 08:57:21 +0000995 int ret;
996 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000997 mpi TA, TB;
998
Paul Bakker6c591fa2011-05-05 11:49:20 +0000999 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001000
1001 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1002 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1003
Paul Bakker23986e52011-04-24 08:57:21 +00001004 for( i = A->n; i > 0; i-- )
1005 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001006 break;
1007
Paul Bakker23986e52011-04-24 08:57:21 +00001008 for( j = B->n; j > 0; j-- )
1009 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001010 break;
1011
Paul Bakker23986e52011-04-24 08:57:21 +00001012 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001013 MPI_CHK( mpi_lset( X, 0 ) );
1014
Paul Bakker23986e52011-04-24 08:57:21 +00001015 for( i++; j > 0; j-- )
1016 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001017
1018 X->s = A->s * B->s;
1019
1020cleanup:
1021
Paul Bakker6c591fa2011-05-05 11:49:20 +00001022 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001023
1024 return( ret );
1025}
1026
1027/*
1028 * Baseline multiplication: X = A * b
1029 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001030int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001031{
1032 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001033 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001034
1035 _B.s = 1;
1036 _B.n = 1;
1037 _B.p = p;
1038 p[0] = b;
1039
1040 return( mpi_mul_mpi( X, A, &_B ) );
1041}
1042
1043/*
1044 * Division by mpi: A = Q * B + R (HAC 14.20)
1045 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001046int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001047{
Paul Bakker23986e52011-04-24 08:57:21 +00001048 int ret;
1049 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001050 mpi X, Y, Z, T1, T2;
1051
1052 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001053 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001054
Paul Bakker6c591fa2011-05-05 11:49:20 +00001055 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1056 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001057
1058 if( mpi_cmp_abs( A, B ) < 0 )
1059 {
1060 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1061 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1062 return( 0 );
1063 }
1064
1065 MPI_CHK( mpi_copy( &X, A ) );
1066 MPI_CHK( mpi_copy( &Y, B ) );
1067 X.s = Y.s = 1;
1068
1069 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1070 MPI_CHK( mpi_lset( &Z, 0 ) );
1071 MPI_CHK( mpi_grow( &T1, 2 ) );
1072 MPI_CHK( mpi_grow( &T2, 3 ) );
1073
1074 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001075 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001076 {
1077 k = biL - 1 - k;
1078 MPI_CHK( mpi_shift_l( &X, k ) );
1079 MPI_CHK( mpi_shift_l( &Y, k ) );
1080 }
1081 else k = 0;
1082
1083 n = X.n - 1;
1084 t = Y.n - 1;
1085 mpi_shift_l( &Y, biL * (n - t) );
1086
1087 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1088 {
1089 Z.p[n - t]++;
1090 mpi_sub_mpi( &X, &X, &Y );
1091 }
1092 mpi_shift_r( &Y, biL * (n - t) );
1093
1094 for( i = n; i > t ; i-- )
1095 {
1096 if( X.p[i] >= Y.p[t] )
1097 Z.p[i - t - 1] = ~0;
1098 else
1099 {
Paul Bakker40e46942009-01-03 21:51:57 +00001100#if defined(POLARSSL_HAVE_LONGLONG)
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001101 t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001102
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001103 r = (t_udbl) X.p[i] << biL;
1104 r |= (t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001105 r /= Y.p[t];
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001106 if( r > ((t_udbl) 1 << biL) - 1)
1107 r = ((t_udbl) 1 << biL) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001108
Paul Bakkera755ca12011-04-24 09:11:17 +00001109 Z.p[i - t - 1] = (t_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001110#else
1111 /*
1112 * __udiv_qrnnd_c, from gmp/longlong.h
1113 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001114 t_uint q0, q1, r0, r1;
1115 t_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001116
1117 d = Y.p[t];
1118 d0 = ( d << biH ) >> biH;
1119 d1 = ( d >> biH );
1120
1121 q1 = X.p[i] / d1;
1122 r1 = X.p[i] - d1 * q1;
1123 r1 <<= biH;
1124 r1 |= ( X.p[i - 1] >> biH );
1125
1126 m = q1 * d0;
1127 if( r1 < m )
1128 {
1129 q1--, r1 += d;
1130 while( r1 >= d && r1 < m )
1131 q1--, r1 += d;
1132 }
1133 r1 -= m;
1134
1135 q0 = r1 / d1;
1136 r0 = r1 - d1 * q0;
1137 r0 <<= biH;
1138 r0 |= ( X.p[i - 1] << biH ) >> biH;
1139
1140 m = q0 * d0;
1141 if( r0 < m )
1142 {
1143 q0--, r0 += d;
1144 while( r0 >= d && r0 < m )
1145 q0--, r0 += d;
1146 }
1147 r0 -= m;
1148
1149 Z.p[i - t - 1] = ( q1 << biH ) | q0;
1150#endif
1151 }
1152
1153 Z.p[i - t - 1]++;
1154 do
1155 {
1156 Z.p[i - t - 1]--;
1157
1158 MPI_CHK( mpi_lset( &T1, 0 ) );
1159 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1160 T1.p[1] = Y.p[t];
1161 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1162
1163 MPI_CHK( mpi_lset( &T2, 0 ) );
1164 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1165 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1166 T2.p[2] = X.p[i];
1167 }
1168 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1169
1170 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1171 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1172 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1173
1174 if( mpi_cmp_int( &X, 0 ) < 0 )
1175 {
1176 MPI_CHK( mpi_copy( &T1, &Y ) );
1177 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1178 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1179 Z.p[i - t - 1]--;
1180 }
1181 }
1182
1183 if( Q != NULL )
1184 {
1185 mpi_copy( Q, &Z );
1186 Q->s = A->s * B->s;
1187 }
1188
1189 if( R != NULL )
1190 {
1191 mpi_shift_r( &X, k );
1192 mpi_copy( R, &X );
1193
1194 R->s = A->s;
1195 if( mpi_cmp_int( R, 0 ) == 0 )
1196 R->s = 1;
1197 }
1198
1199cleanup:
1200
Paul Bakker6c591fa2011-05-05 11:49:20 +00001201 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1202 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001203
1204 return( ret );
1205}
1206
1207/*
1208 * Division by int: A = Q * b + R
1209 *
1210 * Returns 0 if successful
1211 * 1 if memory allocation failed
Paul Bakker40e46942009-01-03 21:51:57 +00001212 * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
Paul Bakker5121ce52009-01-03 21:22:43 +00001213 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001214int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001215{
1216 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001217 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001218
1219 p[0] = ( b < 0 ) ? -b : b;
1220 _B.s = ( b < 0 ) ? -1 : 1;
1221 _B.n = 1;
1222 _B.p = p;
1223
1224 return( mpi_div_mpi( Q, R, A, &_B ) );
1225}
1226
1227/*
1228 * Modulo: R = A mod B
1229 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001230int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001231{
1232 int ret;
1233
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001234 if( mpi_cmp_int( B, 0 ) < 0 )
1235 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1236
Paul Bakker5121ce52009-01-03 21:22:43 +00001237 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1238
1239 while( mpi_cmp_int( R, 0 ) < 0 )
1240 MPI_CHK( mpi_add_mpi( R, R, B ) );
1241
1242 while( mpi_cmp_mpi( R, B ) >= 0 )
1243 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1244
1245cleanup:
1246
1247 return( ret );
1248}
1249
1250/*
1251 * Modulo: r = A mod b
1252 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001253int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001254{
Paul Bakker23986e52011-04-24 08:57:21 +00001255 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001256 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001257
1258 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001259 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001260
1261 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001262 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001263
1264 /*
1265 * handle trivial cases
1266 */
1267 if( b == 1 )
1268 {
1269 *r = 0;
1270 return( 0 );
1271 }
1272
1273 if( b == 2 )
1274 {
1275 *r = A->p[0] & 1;
1276 return( 0 );
1277 }
1278
1279 /*
1280 * general case
1281 */
Paul Bakker23986e52011-04-24 08:57:21 +00001282 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001283 {
Paul Bakker23986e52011-04-24 08:57:21 +00001284 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001285 y = ( y << biH ) | ( x >> biH );
1286 z = y / b;
1287 y -= z * b;
1288
1289 x <<= biH;
1290 y = ( y << biH ) | ( x >> biH );
1291 z = y / b;
1292 y -= z * b;
1293 }
1294
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001295 /*
1296 * If A is negative, then the current y represents a negative value.
1297 * Flipping it to the positive side.
1298 */
1299 if( A->s < 0 && y != 0 )
1300 y = b - y;
1301
Paul Bakker5121ce52009-01-03 21:22:43 +00001302 *r = y;
1303
1304 return( 0 );
1305}
1306
1307/*
1308 * Fast Montgomery initialization (thanks to Tom St Denis)
1309 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001310static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001311{
Paul Bakkera755ca12011-04-24 09:11:17 +00001312 t_uint x, m0 = N->p[0];
Paul Bakker5121ce52009-01-03 21:22:43 +00001313
1314 x = m0;
1315 x += ( ( m0 + 2 ) & 4 ) << 1;
1316 x *= ( 2 - ( m0 * x ) );
1317
1318 if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
1319 if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
1320 if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
1321
1322 *mm = ~x + 1;
1323}
1324
1325/*
1326 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1327 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001328static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001329{
Paul Bakker23986e52011-04-24 08:57:21 +00001330 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001331 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001332
1333 memset( T->p, 0, T->n * ciL );
1334
1335 d = T->p;
1336 n = N->n;
1337 m = ( B->n < n ) ? B->n : n;
1338
1339 for( i = 0; i < n; i++ )
1340 {
1341 /*
1342 * T = (T + u0*B + u1*N) / 2^biL
1343 */
1344 u0 = A->p[i];
1345 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1346
1347 mpi_mul_hlp( m, B->p, d, u0 );
1348 mpi_mul_hlp( n, N->p, d, u1 );
1349
1350 *d++ = u0; d[n + 1] = 0;
1351 }
1352
1353 memcpy( A->p, d, (n + 1) * ciL );
1354
1355 if( mpi_cmp_abs( A, N ) >= 0 )
1356 mpi_sub_hlp( n, N->p, A->p );
1357 else
1358 /* prevent timing attacks */
1359 mpi_sub_hlp( n, A->p, T->p );
1360}
1361
1362/*
1363 * Montgomery reduction: A = A * R^-1 mod N
1364 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001365static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001366{
Paul Bakkera755ca12011-04-24 09:11:17 +00001367 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001368 mpi U;
1369
1370 U.n = U.s = z;
1371 U.p = &z;
1372
1373 mpi_montmul( A, &U, N, mm, T );
1374}
1375
1376/*
1377 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1378 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001379int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001380{
Paul Bakker23986e52011-04-24 08:57:21 +00001381 int ret;
1382 size_t wbits, wsize, one = 1;
1383 size_t i, j, nblimbs;
1384 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001385 t_uint ei, mm, state;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001386 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +00001387
1388 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001389 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001390
1391 /*
1392 * Init temps and window size
1393 */
1394 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001395 mpi_init( &RR ); mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001396 memset( W, 0, sizeof( W ) );
1397
1398 i = mpi_msb( E );
1399
1400 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1401 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1402
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001403 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1404 wsize = POLARSSL_MPI_WINDOW_SIZE;
1405
Paul Bakker5121ce52009-01-03 21:22:43 +00001406 j = N->n + 1;
1407 MPI_CHK( mpi_grow( X, j ) );
1408 MPI_CHK( mpi_grow( &W[1], j ) );
1409 MPI_CHK( mpi_grow( &T, j * 2 ) );
1410
1411 /*
1412 * If 1st call, pre-compute R^2 mod N
1413 */
1414 if( _RR == NULL || _RR->p == NULL )
1415 {
1416 MPI_CHK( mpi_lset( &RR, 1 ) );
1417 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1418 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1419
1420 if( _RR != NULL )
1421 memcpy( _RR, &RR, sizeof( mpi ) );
1422 }
1423 else
1424 memcpy( &RR, _RR, sizeof( mpi ) );
1425
1426 /*
1427 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1428 */
1429 if( mpi_cmp_mpi( A, N ) >= 0 )
1430 mpi_mod_mpi( &W[1], A, N );
1431 else mpi_copy( &W[1], A );
1432
1433 mpi_montmul( &W[1], &RR, N, mm, &T );
1434
1435 /*
1436 * X = R^2 * R^-1 mod N = R mod N
1437 */
1438 MPI_CHK( mpi_copy( X, &RR ) );
1439 mpi_montred( X, N, mm, &T );
1440
1441 if( wsize > 1 )
1442 {
1443 /*
1444 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1445 */
Paul Bakker23986e52011-04-24 08:57:21 +00001446 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001447
1448 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1449 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1450
1451 for( i = 0; i < wsize - 1; i++ )
1452 mpi_montmul( &W[j], &W[j], N, mm, &T );
1453
1454 /*
1455 * W[i] = W[i - 1] * W[1]
1456 */
Paul Bakker23986e52011-04-24 08:57:21 +00001457 for( i = j + 1; i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001458 {
1459 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1460 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1461
1462 mpi_montmul( &W[i], &W[1], N, mm, &T );
1463 }
1464 }
1465
1466 nblimbs = E->n;
1467 bufsize = 0;
1468 nbits = 0;
1469 wbits = 0;
1470 state = 0;
1471
1472 while( 1 )
1473 {
1474 if( bufsize == 0 )
1475 {
1476 if( nblimbs-- == 0 )
1477 break;
1478
Paul Bakkera755ca12011-04-24 09:11:17 +00001479 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001480 }
1481
1482 bufsize--;
1483
1484 ei = (E->p[nblimbs] >> bufsize) & 1;
1485
1486 /*
1487 * skip leading 0s
1488 */
1489 if( ei == 0 && state == 0 )
1490 continue;
1491
1492 if( ei == 0 && state == 1 )
1493 {
1494 /*
1495 * out of window, square X
1496 */
1497 mpi_montmul( X, X, N, mm, &T );
1498 continue;
1499 }
1500
1501 /*
1502 * add ei to current window
1503 */
1504 state = 2;
1505
1506 nbits++;
1507 wbits |= (ei << (wsize - nbits));
1508
1509 if( nbits == wsize )
1510 {
1511 /*
1512 * X = X^wsize R^-1 mod N
1513 */
1514 for( i = 0; i < wsize; i++ )
1515 mpi_montmul( X, X, N, mm, &T );
1516
1517 /*
1518 * X = X * W[wbits] R^-1 mod N
1519 */
1520 mpi_montmul( X, &W[wbits], N, mm, &T );
1521
1522 state--;
1523 nbits = 0;
1524 wbits = 0;
1525 }
1526 }
1527
1528 /*
1529 * process the remaining bits
1530 */
1531 for( i = 0; i < nbits; i++ )
1532 {
1533 mpi_montmul( X, X, N, mm, &T );
1534
1535 wbits <<= 1;
1536
Paul Bakker23986e52011-04-24 08:57:21 +00001537 if( (wbits & (one << wsize)) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001538 mpi_montmul( X, &W[1], N, mm, &T );
1539 }
1540
1541 /*
1542 * X = A^E * R * R^-1 mod N = A^E mod N
1543 */
1544 mpi_montred( X, N, mm, &T );
1545
1546cleanup:
1547
Paul Bakker23986e52011-04-24 08:57:21 +00001548 for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001549 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001550
Paul Bakker6c591fa2011-05-05 11:49:20 +00001551 mpi_free( &W[1] ); mpi_free( &T );
1552
1553 if( _RR == NULL )
1554 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001555
1556 return( ret );
1557}
1558
Paul Bakker5121ce52009-01-03 21:22:43 +00001559/*
1560 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1561 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001562int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001563{
Paul Bakker23986e52011-04-24 08:57:21 +00001564 int ret;
1565 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001566 mpi TG, TA, TB;
1567
Paul Bakker6c591fa2011-05-05 11:49:20 +00001568 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001569
Paul Bakker5121ce52009-01-03 21:22:43 +00001570 MPI_CHK( mpi_copy( &TA, A ) );
1571 MPI_CHK( mpi_copy( &TB, B ) );
1572
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001573 lz = mpi_lsb( &TA );
1574 lzt = mpi_lsb( &TB );
1575
1576 if ( lzt < lz )
1577 lz = lzt;
1578
1579 MPI_CHK( mpi_shift_r( &TA, lz ) );
1580 MPI_CHK( mpi_shift_r( &TB, lz ) );
1581
Paul Bakker5121ce52009-01-03 21:22:43 +00001582 TA.s = TB.s = 1;
1583
1584 while( mpi_cmp_int( &TA, 0 ) != 0 )
1585 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001586 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1587 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001588
1589 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1590 {
1591 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1592 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1593 }
1594 else
1595 {
1596 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1597 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1598 }
1599 }
1600
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001601 MPI_CHK( mpi_shift_l( &TB, lz ) );
1602 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001603
1604cleanup:
1605
Paul Bakker6c591fa2011-05-05 11:49:20 +00001606 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001607
1608 return( ret );
1609}
1610
Paul Bakker23986e52011-04-24 08:57:21 +00001611int mpi_fill_random( mpi *X, size_t size, int (*f_rng)(void *), void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001612{
Paul Bakker23986e52011-04-24 08:57:21 +00001613 int ret;
1614 size_t k;
Paul Bakker287781a2011-03-26 13:18:49 +00001615 unsigned char *p;
1616
1617 MPI_CHK( mpi_grow( X, size ) );
1618 MPI_CHK( mpi_lset( X, 0 ) );
1619
1620 p = (unsigned char *) X->p;
1621 for( k = 0; k < X->n * ciL; k++ )
1622 *p++ = (unsigned char) f_rng( p_rng );
1623
1624cleanup:
1625 return( ret );
1626}
1627
Paul Bakker70b3eed2009-03-14 18:01:25 +00001628#if defined(POLARSSL_GENPRIME)
1629
Paul Bakker5121ce52009-01-03 21:22:43 +00001630/*
1631 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1632 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001633int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001634{
1635 int ret;
1636 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1637
1638 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001639 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001640
Paul Bakker6c591fa2011-05-05 11:49:20 +00001641 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1642 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1643 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001644
1645 MPI_CHK( mpi_gcd( &G, A, N ) );
1646
1647 if( mpi_cmp_int( &G, 1 ) != 0 )
1648 {
Paul Bakker40e46942009-01-03 21:51:57 +00001649 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001650 goto cleanup;
1651 }
1652
1653 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1654 MPI_CHK( mpi_copy( &TU, &TA ) );
1655 MPI_CHK( mpi_copy( &TB, N ) );
1656 MPI_CHK( mpi_copy( &TV, N ) );
1657
1658 MPI_CHK( mpi_lset( &U1, 1 ) );
1659 MPI_CHK( mpi_lset( &U2, 0 ) );
1660 MPI_CHK( mpi_lset( &V1, 0 ) );
1661 MPI_CHK( mpi_lset( &V2, 1 ) );
1662
1663 do
1664 {
1665 while( ( TU.p[0] & 1 ) == 0 )
1666 {
1667 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1668
1669 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1670 {
1671 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1672 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1673 }
1674
1675 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1676 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1677 }
1678
1679 while( ( TV.p[0] & 1 ) == 0 )
1680 {
1681 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1682
1683 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1684 {
1685 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1686 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1687 }
1688
1689 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1690 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1691 }
1692
1693 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1694 {
1695 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1696 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1697 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1698 }
1699 else
1700 {
1701 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1702 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1703 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1704 }
1705 }
1706 while( mpi_cmp_int( &TU, 0 ) != 0 );
1707
1708 while( mpi_cmp_int( &V1, 0 ) < 0 )
1709 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1710
1711 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1712 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1713
1714 MPI_CHK( mpi_copy( X, &V1 ) );
1715
1716cleanup:
1717
Paul Bakker6c591fa2011-05-05 11:49:20 +00001718 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1719 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1720 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001721
1722 return( ret );
1723}
1724
1725static const int small_prime[] =
1726{
1727 3, 5, 7, 11, 13, 17, 19, 23,
1728 29, 31, 37, 41, 43, 47, 53, 59,
1729 61, 67, 71, 73, 79, 83, 89, 97,
1730 101, 103, 107, 109, 113, 127, 131, 137,
1731 139, 149, 151, 157, 163, 167, 173, 179,
1732 181, 191, 193, 197, 199, 211, 223, 227,
1733 229, 233, 239, 241, 251, 257, 263, 269,
1734 271, 277, 281, 283, 293, 307, 311, 313,
1735 317, 331, 337, 347, 349, 353, 359, 367,
1736 373, 379, 383, 389, 397, 401, 409, 419,
1737 421, 431, 433, 439, 443, 449, 457, 461,
1738 463, 467, 479, 487, 491, 499, 503, 509,
1739 521, 523, 541, 547, 557, 563, 569, 571,
1740 577, 587, 593, 599, 601, 607, 613, 617,
1741 619, 631, 641, 643, 647, 653, 659, 661,
1742 673, 677, 683, 691, 701, 709, 719, 727,
1743 733, 739, 743, 751, 757, 761, 769, 773,
1744 787, 797, 809, 811, 821, 823, 827, 829,
1745 839, 853, 857, 859, 863, 877, 881, 883,
1746 887, 907, 911, 919, 929, 937, 941, 947,
1747 953, 967, 971, 977, 983, 991, 997, -103
1748};
1749
1750/*
1751 * Miller-Rabin primality test (HAC 4.24)
1752 */
1753int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng )
1754{
Paul Bakker23986e52011-04-24 08:57:21 +00001755 int ret, xs;
1756 size_t i, j, n, s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001757 mpi W, R, T, A, RR;
Paul Bakker5121ce52009-01-03 21:22:43 +00001758
Paul Bakker48eab262009-06-25 21:25:49 +00001759 if( mpi_cmp_int( X, 0 ) == 0 ||
1760 mpi_cmp_int( X, 1 ) == 0 )
1761 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1762
1763 if( mpi_cmp_int( X, 2 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001764 return( 0 );
1765
Paul Bakker6c591fa2011-05-05 11:49:20 +00001766 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
1767 mpi_init( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001768
1769 xs = X->s; X->s = 1;
1770
1771 /*
1772 * test trivial factors first
1773 */
1774 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001775 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001776
1777 for( i = 0; small_prime[i] > 0; i++ )
1778 {
Paul Bakkera755ca12011-04-24 09:11:17 +00001779 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001780
1781 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
1782 return( 0 );
1783
1784 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1785
1786 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001787 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001788 }
1789
1790 /*
1791 * W = |X| - 1
1792 * R = W >> lsb( W )
1793 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001794 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001795 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001796 MPI_CHK( mpi_copy( &R, &W ) );
1797 MPI_CHK( mpi_shift_r( &R, s ) );
1798
1799 i = mpi_msb( X );
1800 /*
1801 * HAC, table 4.4
1802 */
1803 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1804 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1805 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1806
1807 for( i = 0; i < n; i++ )
1808 {
1809 /*
1810 * pick a random A, 1 < A < |X| - 1
1811 */
Paul Bakker287781a2011-03-26 13:18:49 +00001812 mpi_fill_random( &A, X->n, f_rng, p_rng );
Paul Bakker5121ce52009-01-03 21:22:43 +00001813
Paul Bakkerb94081b2011-01-05 15:53:06 +00001814 if( mpi_cmp_mpi( &A, &W ) >= 0 )
1815 {
1816 j = mpi_msb( &A ) - mpi_msb( &W );
1817 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1818 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001819 A.p[0] |= 3;
1820
1821 /*
1822 * A = A^R mod |X|
1823 */
1824 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1825
1826 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1827 mpi_cmp_int( &A, 1 ) == 0 )
1828 continue;
1829
1830 j = 1;
1831 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1832 {
1833 /*
1834 * A = A * A mod |X|
1835 */
1836 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1837 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1838
1839 if( mpi_cmp_int( &A, 1 ) == 0 )
1840 break;
1841
1842 j++;
1843 }
1844
1845 /*
1846 * not prime if A != |X| - 1 or A == 1
1847 */
1848 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1849 mpi_cmp_int( &A, 1 ) == 0 )
1850 {
Paul Bakker40e46942009-01-03 21:51:57 +00001851 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001852 break;
1853 }
1854 }
1855
1856cleanup:
1857
1858 X->s = xs;
1859
Paul Bakker6c591fa2011-05-05 11:49:20 +00001860 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
1861 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001862
1863 return( ret );
1864}
1865
1866/*
1867 * Prime number generation
1868 */
Paul Bakker23986e52011-04-24 08:57:21 +00001869int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakker5121ce52009-01-03 21:22:43 +00001870 int (*f_rng)(void *), void *p_rng )
1871{
Paul Bakker23986e52011-04-24 08:57:21 +00001872 int ret;
1873 size_t k, n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001874 mpi Y;
1875
Paul Bakkerfe3256e2011-11-25 12:11:43 +00001876 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00001877 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001878
Paul Bakker6c591fa2011-05-05 11:49:20 +00001879 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001880
1881 n = BITS_TO_LIMBS( nbits );
1882
Paul Bakker287781a2011-03-26 13:18:49 +00001883 mpi_fill_random( X, n, f_rng, p_rng );
Paul Bakker5121ce52009-01-03 21:22:43 +00001884
1885 k = mpi_msb( X );
1886 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
1887 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
1888
1889 X->p[0] |= 3;
1890
1891 if( dh_flag == 0 )
1892 {
1893 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
1894 {
Paul Bakker40e46942009-01-03 21:51:57 +00001895 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001896 goto cleanup;
1897
1898 MPI_CHK( mpi_add_int( X, X, 2 ) );
1899 }
1900 }
1901 else
1902 {
1903 MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
1904 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1905
1906 while( 1 )
1907 {
1908 if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
1909 {
1910 if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
1911 break;
1912
Paul Bakker40e46942009-01-03 21:51:57 +00001913 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001914 goto cleanup;
1915 }
1916
Paul Bakker40e46942009-01-03 21:51:57 +00001917 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001918 goto cleanup;
1919
1920 MPI_CHK( mpi_add_int( &Y, X, 1 ) );
1921 MPI_CHK( mpi_add_int( X, X, 2 ) );
1922 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1923 }
1924 }
1925
1926cleanup:
1927
Paul Bakker6c591fa2011-05-05 11:49:20 +00001928 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00001929
1930 return( ret );
1931}
1932
1933#endif
1934
Paul Bakker40e46942009-01-03 21:51:57 +00001935#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00001936
Paul Bakker23986e52011-04-24 08:57:21 +00001937#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001938
1939static const int gcd_pairs[GCD_PAIR_COUNT][3] =
1940{
1941 { 693, 609, 21 },
1942 { 1764, 868, 28 },
1943 { 768454923, 542167814, 1 }
1944};
1945
Paul Bakker5121ce52009-01-03 21:22:43 +00001946/*
1947 * Checkup routine
1948 */
1949int mpi_self_test( int verbose )
1950{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001951 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001952 mpi A, E, N, X, Y, U, V;
1953
Paul Bakker6c591fa2011-05-05 11:49:20 +00001954 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
1955 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956
1957 MPI_CHK( mpi_read_string( &A, 16,
1958 "EFE021C2645FD1DC586E69184AF4A31E" \
1959 "D5F53E93B5F123FA41680867BA110131" \
1960 "944FE7952E2517337780CB0DB80E61AA" \
1961 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
1962
1963 MPI_CHK( mpi_read_string( &E, 16,
1964 "B2E7EFD37075B9F03FF989C7C5051C20" \
1965 "34D2A323810251127E7BF8625A4F49A5" \
1966 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
1967 "5B5C25763222FEFCCFC38B832366C29E" ) );
1968
1969 MPI_CHK( mpi_read_string( &N, 16,
1970 "0066A198186C18C10B2F5ED9B522752A" \
1971 "9830B69916E535C8F047518A889A43A5" \
1972 "94B6BED27A168D31D4A52F88925AA8F5" ) );
1973
1974 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
1975
1976 MPI_CHK( mpi_read_string( &U, 16,
1977 "602AB7ECA597A3D6B56FF9829A5E8B85" \
1978 "9E857EA95A03512E2BAE7391688D264A" \
1979 "A5663B0341DB9CCFD2C4C5F421FEC814" \
1980 "8001B72E848A38CAE1C65F78E56ABDEF" \
1981 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
1982 "ECF677152EF804370C1A305CAF3B5BF1" \
1983 "30879B56C61DE584A0F53A2447A51E" ) );
1984
1985 if( verbose != 0 )
1986 printf( " MPI test #1 (mul_mpi): " );
1987
1988 if( mpi_cmp_mpi( &X, &U ) != 0 )
1989 {
1990 if( verbose != 0 )
1991 printf( "failed\n" );
1992
1993 return( 1 );
1994 }
1995
1996 if( verbose != 0 )
1997 printf( "passed\n" );
1998
1999 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2000
2001 MPI_CHK( mpi_read_string( &U, 16,
2002 "256567336059E52CAE22925474705F39A94" ) );
2003
2004 MPI_CHK( mpi_read_string( &V, 16,
2005 "6613F26162223DF488E9CD48CC132C7A" \
2006 "0AC93C701B001B092E4E5B9F73BCD27B" \
2007 "9EE50D0657C77F374E903CDFA4C642" ) );
2008
2009 if( verbose != 0 )
2010 printf( " MPI test #2 (div_mpi): " );
2011
2012 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2013 mpi_cmp_mpi( &Y, &V ) != 0 )
2014 {
2015 if( verbose != 0 )
2016 printf( "failed\n" );
2017
2018 return( 1 );
2019 }
2020
2021 if( verbose != 0 )
2022 printf( "passed\n" );
2023
2024 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2025
2026 MPI_CHK( mpi_read_string( &U, 16,
2027 "36E139AEA55215609D2816998ED020BB" \
2028 "BD96C37890F65171D948E9BC7CBAA4D9" \
2029 "325D24D6A3C12710F10A09FA08AB87" ) );
2030
2031 if( verbose != 0 )
2032 printf( " MPI test #3 (exp_mod): " );
2033
2034 if( mpi_cmp_mpi( &X, &U ) != 0 )
2035 {
2036 if( verbose != 0 )
2037 printf( "failed\n" );
2038
2039 return( 1 );
2040 }
2041
2042 if( verbose != 0 )
2043 printf( "passed\n" );
2044
Paul Bakker5690efc2011-05-26 13:16:06 +00002045#if defined(POLARSSL_GENPRIME)
Paul Bakker5121ce52009-01-03 21:22:43 +00002046 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2047
2048 MPI_CHK( mpi_read_string( &U, 16,
2049 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2050 "C3DBA76456363A10869622EAC2DD84EC" \
2051 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2052
2053 if( verbose != 0 )
2054 printf( " MPI test #4 (inv_mod): " );
2055
2056 if( mpi_cmp_mpi( &X, &U ) != 0 )
2057 {
2058 if( verbose != 0 )
2059 printf( "failed\n" );
2060
2061 return( 1 );
2062 }
2063
2064 if( verbose != 0 )
2065 printf( "passed\n" );
Paul Bakker5690efc2011-05-26 13:16:06 +00002066#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00002067
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002068 if( verbose != 0 )
2069 printf( " MPI test #5 (simple gcd): " );
2070
2071 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2072 {
2073 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002074 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002075
Paul Bakker23986e52011-04-24 08:57:21 +00002076 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002077
Paul Bakker23986e52011-04-24 08:57:21 +00002078 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2079 {
2080 if( verbose != 0 )
2081 printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002082
Paul Bakker23986e52011-04-24 08:57:21 +00002083 return( 1 );
2084 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002085 }
2086
2087 if( verbose != 0 )
2088 printf( "passed\n" );
2089
Paul Bakker5121ce52009-01-03 21:22:43 +00002090cleanup:
2091
2092 if( ret != 0 && verbose != 0 )
2093 printf( "Unexpected error, return code = %08X\n", ret );
2094
Paul Bakker6c591fa2011-05-05 11:49:20 +00002095 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2096 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002097
2098 if( verbose != 0 )
2099 printf( "\n" );
2100
2101 return( ret );
2102}
2103
2104#endif
2105
2106#endif