blob: 98d534a5a9d4eb7bd45017554a4ba797f70cc9f0 [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 Bakker6e339b52013-07-03 13:37:05 +020040#if defined(POLARSSL_MEMORY_C)
41#include "polarssl/memory.h"
42#else
43#define polarssl_malloc malloc
44#define polarssl_free free
45#endif
46
Paul Bakker5121ce52009-01-03 21:22:43 +000047#include <stdlib.h>
Paul Bakker5121ce52009-01-03 21:22:43 +000048
Paul Bakkerf9688572011-05-05 10:00:45 +000049#define ciL (sizeof(t_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000050#define biL (ciL << 3) /* bits in limb */
51#define biH (ciL << 2) /* half limb size */
52
53/*
54 * Convert between bits/chars and number of limbs
55 */
56#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL)
57#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
58
59/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000060 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000061 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000062void mpi_init( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000063{
Paul Bakker6c591fa2011-05-05 11:49:20 +000064 if( X == NULL )
65 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000066
Paul Bakker6c591fa2011-05-05 11:49:20 +000067 X->s = 1;
68 X->n = 0;
69 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000070}
71
72/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000073 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000074 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000075void mpi_free( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000076{
Paul Bakker6c591fa2011-05-05 11:49:20 +000077 if( X == NULL )
78 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000079
Paul Bakker6c591fa2011-05-05 11:49:20 +000080 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +000081 {
Paul Bakker6c591fa2011-05-05 11:49:20 +000082 memset( X->p, 0, X->n * ciL );
Paul Bakker6e339b52013-07-03 13:37:05 +020083 polarssl_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +000084 }
85
Paul Bakker6c591fa2011-05-05 11:49:20 +000086 X->s = 1;
87 X->n = 0;
88 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000089}
90
91/*
92 * Enlarge to the specified number of limbs
93 */
Paul Bakker23986e52011-04-24 08:57:21 +000094int mpi_grow( mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +000095{
Paul Bakkera755ca12011-04-24 09:11:17 +000096 t_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +000097
Paul Bakkerf9688572011-05-05 10:00:45 +000098 if( nblimbs > POLARSSL_MPI_MAX_LIMBS )
Paul Bakker69e095c2011-12-10 21:55:01 +000099 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000100
Paul Bakker5121ce52009-01-03 21:22:43 +0000101 if( X->n < nblimbs )
102 {
Paul Bakker6e339b52013-07-03 13:37:05 +0200103 if( ( p = (t_uint *) polarssl_malloc( nblimbs * ciL ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000104 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000105
106 memset( p, 0, nblimbs * ciL );
107
108 if( X->p != NULL )
109 {
110 memcpy( p, X->p, X->n * ciL );
111 memset( X->p, 0, X->n * ciL );
Paul Bakker6e339b52013-07-03 13:37:05 +0200112 polarssl_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000113 }
114
115 X->n = nblimbs;
116 X->p = p;
117 }
118
119 return( 0 );
120}
121
122/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100123 * Resize down as much as possible,
124 * while keeping at least the specified number of limbs
125 */
126int mpi_shrink( mpi *X, size_t nblimbs )
127{
128 t_uint *p;
129 size_t i;
130
131 /* Actually resize up in this case */
132 if( X->n <= nblimbs )
133 return( mpi_grow( X, nblimbs ) );
134
135 for( i = X->n - 1; i > 0; i-- )
136 if( X->p[i] != 0 )
137 break;
138 i++;
139
140 if( i < nblimbs )
141 i = nblimbs;
142
143 if( ( p = (t_uint *) polarssl_malloc( i * ciL ) ) == NULL )
144 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
145
146 memset( p, 0, i * ciL );
147
148 if( X->p != NULL )
149 {
150 memcpy( p, X->p, i * ciL );
151 memset( X->p, 0, X->n * ciL );
152 polarssl_free( X->p );
153 }
154
155 X->n = i;
156 X->p = p;
157
158 return( 0 );
159}
160
161/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000162 * Copy the contents of Y into X
163 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000164int mpi_copy( mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000165{
Paul Bakker23986e52011-04-24 08:57:21 +0000166 int ret;
167 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000168
169 if( X == Y )
170 return( 0 );
171
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200172 if( Y->p == NULL )
173 {
174 mpi_free( X );
175 return( 0 );
176 }
177
Paul Bakker5121ce52009-01-03 21:22:43 +0000178 for( i = Y->n - 1; i > 0; i-- )
179 if( Y->p[i] != 0 )
180 break;
181 i++;
182
183 X->s = Y->s;
184
185 MPI_CHK( mpi_grow( X, i ) );
186
187 memset( X->p, 0, X->n * ciL );
188 memcpy( X->p, Y->p, i * ciL );
189
190cleanup:
191
192 return( ret );
193}
194
195/*
196 * Swap the contents of X and Y
197 */
198void mpi_swap( mpi *X, mpi *Y )
199{
200 mpi T;
201
202 memcpy( &T, X, sizeof( mpi ) );
203 memcpy( X, Y, sizeof( mpi ) );
204 memcpy( Y, &T, sizeof( mpi ) );
205}
206
207/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100208 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100209 * about whether the assignment was made or not.
210 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100211 */
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100212int mpi_safe_cond_assign( mpi *X, const mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100213{
214 int ret = 0;
215 size_t i;
216
217 if( assign * ( 1 - assign ) != 0 )
218 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
219
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100220 if( Y->n > X->n )
221 MPI_CHK( mpi_grow( X, Y->n ) );
222
223 /* Do the conditional assign safely */
Manuel Pégourié-Gonnard3e3d2b82013-11-21 21:12:26 +0100224 X->s = X->s * (1 - assign) + Y->s * assign;
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100225 for( i = 0; i < Y->n; i++ )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100226 X->p[i] = X->p[i] * (1 - assign) + Y->p[i] * assign;
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100227 for( ; i < X->n; i++ )
228 X->p[i] *= (1 - assign);
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100229
230cleanup:
231 return( ret );
232}
233
234/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000235 * Set value from integer
236 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000237int mpi_lset( mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000238{
239 int ret;
240
241 MPI_CHK( mpi_grow( X, 1 ) );
242 memset( X->p, 0, X->n * ciL );
243
244 X->p[0] = ( z < 0 ) ? -z : z;
245 X->s = ( z < 0 ) ? -1 : 1;
246
247cleanup:
248
249 return( ret );
250}
251
252/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000253 * Get a specific bit
254 */
Paul Bakker6b906e52012-05-08 12:01:43 +0000255int mpi_get_bit( const mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000256{
257 if( X->n * biL <= pos )
258 return( 0 );
259
260 return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
261}
262
263/*
264 * Set a bit to a specific value of 0 or 1
265 */
266int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
267{
268 int ret = 0;
269 size_t off = pos / biL;
270 size_t idx = pos % biL;
271
272 if( val != 0 && val != 1 )
273 return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
274
275 if( X->n * biL <= pos )
276 {
277 if( val == 0 )
278 return ( 0 );
279
280 MPI_CHK( mpi_grow( X, off + 1 ) );
281 }
282
Manuel Pégourié-Gonnard9a4a5ac2013-12-04 18:05:29 +0100283 X->p[off] &= ~( (t_uint) 0x01 << idx );
284 X->p[off] |= (t_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000285
286cleanup:
287
288 return( ret );
289}
290
291/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000292 * Return the number of least significant bits
293 */
Paul Bakker23986e52011-04-24 08:57:21 +0000294size_t mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000295{
Paul Bakker23986e52011-04-24 08:57:21 +0000296 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000297
298 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000299 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000300 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
301 return( count );
302
303 return( 0 );
304}
305
306/*
307 * Return the number of most significant bits
308 */
Paul Bakker23986e52011-04-24 08:57:21 +0000309size_t mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000310{
Paul Bakker23986e52011-04-24 08:57:21 +0000311 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000312
313 for( i = X->n - 1; i > 0; i-- )
314 if( X->p[i] != 0 )
315 break;
316
Paul Bakker23986e52011-04-24 08:57:21 +0000317 for( j = biL; j > 0; j-- )
318 if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000319 break;
320
Paul Bakker23986e52011-04-24 08:57:21 +0000321 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000322}
323
324/*
325 * Return the total size in bytes
326 */
Paul Bakker23986e52011-04-24 08:57:21 +0000327size_t mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000328{
329 return( ( mpi_msb( X ) + 7 ) >> 3 );
330}
331
332/*
333 * Convert an ASCII character to digit value
334 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000335static int mpi_get_digit( t_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000336{
337 *d = 255;
338
339 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
340 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
341 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
342
Paul Bakkera755ca12011-04-24 09:11:17 +0000343 if( *d >= (t_uint) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000344 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000345
346 return( 0 );
347}
348
349/*
350 * Import from an ASCII string
351 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000352int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000353{
Paul Bakker23986e52011-04-24 08:57:21 +0000354 int ret;
355 size_t i, j, slen, n;
Paul Bakkera755ca12011-04-24 09:11:17 +0000356 t_uint d;
Paul Bakker5121ce52009-01-03 21:22:43 +0000357 mpi T;
358
359 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000360 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000361
Paul Bakker6c591fa2011-05-05 11:49:20 +0000362 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000363
Paul Bakkerff60ee62010-03-16 21:09:09 +0000364 slen = strlen( s );
365
Paul Bakker5121ce52009-01-03 21:22:43 +0000366 if( radix == 16 )
367 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000368 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000369
370 MPI_CHK( mpi_grow( X, n ) );
371 MPI_CHK( mpi_lset( X, 0 ) );
372
Paul Bakker23986e52011-04-24 08:57:21 +0000373 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000374 {
Paul Bakker23986e52011-04-24 08:57:21 +0000375 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000376 {
377 X->s = -1;
378 break;
379 }
380
Paul Bakker23986e52011-04-24 08:57:21 +0000381 MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000382 X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
383 }
384 }
385 else
386 {
387 MPI_CHK( mpi_lset( X, 0 ) );
388
Paul Bakkerff60ee62010-03-16 21:09:09 +0000389 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000390 {
391 if( i == 0 && s[i] == '-' )
392 {
393 X->s = -1;
394 continue;
395 }
396
397 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
398 MPI_CHK( mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000399
400 if( X->s == 1 )
401 {
402 MPI_CHK( mpi_add_int( X, &T, d ) );
403 }
404 else
405 {
406 MPI_CHK( mpi_sub_int( X, &T, d ) );
407 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000408 }
409 }
410
411cleanup:
412
Paul Bakker6c591fa2011-05-05 11:49:20 +0000413 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000414
415 return( ret );
416}
417
418/*
419 * Helper to write the digits high-order first
420 */
421static int mpi_write_hlp( mpi *X, int radix, char **p )
422{
423 int ret;
Paul Bakkera755ca12011-04-24 09:11:17 +0000424 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000425
426 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000427 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000428
429 MPI_CHK( mpi_mod_int( &r, X, radix ) );
430 MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
431
432 if( mpi_cmp_int( X, 0 ) != 0 )
433 MPI_CHK( mpi_write_hlp( X, radix, p ) );
434
435 if( r < 10 )
436 *(*p)++ = (char)( r + 0x30 );
437 else
438 *(*p)++ = (char)( r + 0x37 );
439
440cleanup:
441
442 return( ret );
443}
444
445/*
446 * Export into an ASCII string
447 */
Paul Bakker23986e52011-04-24 08:57:21 +0000448int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000449{
Paul Bakker23986e52011-04-24 08:57:21 +0000450 int ret = 0;
451 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000452 char *p;
453 mpi T;
454
455 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000456 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000457
458 n = mpi_msb( X );
459 if( radix >= 4 ) n >>= 1;
460 if( radix >= 16 ) n >>= 1;
461 n += 3;
462
463 if( *slen < n )
464 {
465 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000466 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000467 }
468
469 p = s;
Paul Bakker6c591fa2011-05-05 11:49:20 +0000470 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000471
472 if( X->s == -1 )
473 *p++ = '-';
474
475 if( radix == 16 )
476 {
Paul Bakker23986e52011-04-24 08:57:21 +0000477 int c;
478 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000479
Paul Bakker23986e52011-04-24 08:57:21 +0000480 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000481 {
Paul Bakker23986e52011-04-24 08:57:21 +0000482 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000483 {
Paul Bakker23986e52011-04-24 08:57:21 +0000484 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000485
Paul Bakker23986e52011-04-24 08:57:21 +0000486 if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000487 continue;
488
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000489 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000490 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000491 k = 1;
492 }
493 }
494 }
495 else
496 {
497 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000498
499 if( T.s == -1 )
500 T.s = 1;
501
Paul Bakker5121ce52009-01-03 21:22:43 +0000502 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
503 }
504
505 *p++ = '\0';
506 *slen = p - s;
507
508cleanup:
509
Paul Bakker6c591fa2011-05-05 11:49:20 +0000510 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000511
512 return( ret );
513}
514
Paul Bakker335db3f2011-04-25 15:28:35 +0000515#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000516/*
517 * Read X from an opened file
518 */
519int mpi_read_file( mpi *X, int radix, FILE *fin )
520{
Paul Bakkera755ca12011-04-24 09:11:17 +0000521 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000522 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000523 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000524 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000525 * Buffer should have space for (short) label and decimal formatted MPI,
526 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000527 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000528 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000529
530 memset( s, 0, sizeof( s ) );
531 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000532 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000533
534 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000535 if( slen == sizeof( s ) - 2 )
536 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
537
Paul Bakker5121ce52009-01-03 21:22:43 +0000538 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
539 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
540
541 p = s + slen;
542 while( --p >= s )
543 if( mpi_get_digit( &d, radix, *p ) != 0 )
544 break;
545
546 return( mpi_read_string( X, radix, p + 1 ) );
547}
548
549/*
550 * Write X into an opened file (or stdout if fout == NULL)
551 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000552int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000553{
Paul Bakker23986e52011-04-24 08:57:21 +0000554 int ret;
555 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000556 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000557 * Buffer should have space for (short) label and decimal formatted MPI,
558 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000559 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000560 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000561
562 n = sizeof( s );
563 memset( s, 0, n );
564 n -= 2;
565
Paul Bakker23986e52011-04-24 08:57:21 +0000566 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000567
568 if( p == NULL ) p = "";
569
570 plen = strlen( p );
571 slen = strlen( s );
572 s[slen++] = '\r';
573 s[slen++] = '\n';
574
575 if( fout != NULL )
576 {
577 if( fwrite( p, 1, plen, fout ) != plen ||
578 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000579 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000580 }
581 else
582 printf( "%s%s", p, s );
583
584cleanup:
585
586 return( ret );
587}
Paul Bakker335db3f2011-04-25 15:28:35 +0000588#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000589
590/*
591 * Import X from unsigned binary data, big endian
592 */
Paul Bakker23986e52011-04-24 08:57:21 +0000593int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000594{
Paul Bakker23986e52011-04-24 08:57:21 +0000595 int ret;
596 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000597
598 for( n = 0; n < buflen; n++ )
599 if( buf[n] != 0 )
600 break;
601
602 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
603 MPI_CHK( mpi_lset( X, 0 ) );
604
Paul Bakker23986e52011-04-24 08:57:21 +0000605 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000606 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000607
608cleanup:
609
610 return( ret );
611}
612
613/*
614 * Export X into unsigned binary data, big endian
615 */
Paul Bakker23986e52011-04-24 08:57:21 +0000616int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000617{
Paul Bakker23986e52011-04-24 08:57:21 +0000618 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000619
620 n = mpi_size( X );
621
622 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000623 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000624
625 memset( buf, 0, buflen );
626
627 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
628 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
629
630 return( 0 );
631}
632
633/*
634 * Left-shift: X <<= count
635 */
Paul Bakker23986e52011-04-24 08:57:21 +0000636int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000637{
Paul Bakker23986e52011-04-24 08:57:21 +0000638 int ret;
639 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000640 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000641
642 v0 = count / (biL );
643 t1 = count & (biL - 1);
644
645 i = mpi_msb( X ) + count;
646
Paul Bakkerf9688572011-05-05 10:00:45 +0000647 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000648 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
649
650 ret = 0;
651
652 /*
653 * shift by count / limb_size
654 */
655 if( v0 > 0 )
656 {
Paul Bakker23986e52011-04-24 08:57:21 +0000657 for( i = X->n; i > v0; i-- )
658 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000659
Paul Bakker23986e52011-04-24 08:57:21 +0000660 for( ; i > 0; i-- )
661 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000662 }
663
664 /*
665 * shift by count % limb_size
666 */
667 if( t1 > 0 )
668 {
669 for( i = v0; i < X->n; i++ )
670 {
671 r1 = X->p[i] >> (biL - t1);
672 X->p[i] <<= t1;
673 X->p[i] |= r0;
674 r0 = r1;
675 }
676 }
677
678cleanup:
679
680 return( ret );
681}
682
683/*
684 * Right-shift: X >>= count
685 */
Paul Bakker23986e52011-04-24 08:57:21 +0000686int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000687{
Paul Bakker23986e52011-04-24 08:57:21 +0000688 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000689 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000690
691 v0 = count / biL;
692 v1 = count & (biL - 1);
693
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100694 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
695 return mpi_lset( X, 0 );
696
Paul Bakker5121ce52009-01-03 21:22:43 +0000697 /*
698 * shift by count / limb_size
699 */
700 if( v0 > 0 )
701 {
702 for( i = 0; i < X->n - v0; i++ )
703 X->p[i] = X->p[i + v0];
704
705 for( ; i < X->n; i++ )
706 X->p[i] = 0;
707 }
708
709 /*
710 * shift by count % limb_size
711 */
712 if( v1 > 0 )
713 {
Paul Bakker23986e52011-04-24 08:57:21 +0000714 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000715 {
Paul Bakker23986e52011-04-24 08:57:21 +0000716 r1 = X->p[i - 1] << (biL - v1);
717 X->p[i - 1] >>= v1;
718 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000719 r0 = r1;
720 }
721 }
722
723 return( 0 );
724}
725
726/*
727 * Compare unsigned values
728 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000729int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000730{
Paul Bakker23986e52011-04-24 08:57:21 +0000731 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000732
Paul Bakker23986e52011-04-24 08:57:21 +0000733 for( i = X->n; i > 0; i-- )
734 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000735 break;
736
Paul Bakker23986e52011-04-24 08:57:21 +0000737 for( j = Y->n; j > 0; j-- )
738 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000739 break;
740
Paul Bakker23986e52011-04-24 08:57:21 +0000741 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000742 return( 0 );
743
744 if( i > j ) return( 1 );
745 if( j > i ) return( -1 );
746
Paul Bakker23986e52011-04-24 08:57:21 +0000747 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000748 {
Paul Bakker23986e52011-04-24 08:57:21 +0000749 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
750 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000751 }
752
753 return( 0 );
754}
755
756/*
757 * Compare signed values
758 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000759int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000760{
Paul Bakker23986e52011-04-24 08:57:21 +0000761 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000762
Paul Bakker23986e52011-04-24 08:57:21 +0000763 for( i = X->n; i > 0; i-- )
764 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000765 break;
766
Paul Bakker23986e52011-04-24 08:57:21 +0000767 for( j = Y->n; j > 0; j-- )
768 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000769 break;
770
Paul Bakker23986e52011-04-24 08:57:21 +0000771 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000772 return( 0 );
773
774 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000775 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000776
777 if( X->s > 0 && Y->s < 0 ) return( 1 );
778 if( Y->s > 0 && X->s < 0 ) return( -1 );
779
Paul Bakker23986e52011-04-24 08:57:21 +0000780 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000781 {
Paul Bakker23986e52011-04-24 08:57:21 +0000782 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
783 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000784 }
785
786 return( 0 );
787}
788
789/*
790 * Compare signed values
791 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000792int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000793{
794 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000795 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000796
797 *p = ( z < 0 ) ? -z : z;
798 Y.s = ( z < 0 ) ? -1 : 1;
799 Y.n = 1;
800 Y.p = p;
801
802 return( mpi_cmp_mpi( X, &Y ) );
803}
804
805/*
806 * Unsigned addition: X = |A| + |B| (HAC 14.7)
807 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000808int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000809{
Paul Bakker23986e52011-04-24 08:57:21 +0000810 int ret;
811 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000812 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000813
814 if( X == B )
815 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000816 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000817 }
818
819 if( X != A )
820 MPI_CHK( mpi_copy( X, A ) );
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000821
822 /*
823 * X should always be positive as a result of unsigned additions.
824 */
825 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000826
Paul Bakker23986e52011-04-24 08:57:21 +0000827 for( j = B->n; j > 0; j-- )
828 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000829 break;
830
Paul Bakker23986e52011-04-24 08:57:21 +0000831 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000832
833 o = B->p; p = X->p; c = 0;
834
Paul Bakker23986e52011-04-24 08:57:21 +0000835 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000836 {
837 *p += c; c = ( *p < c );
838 *p += *o; c += ( *p < *o );
839 }
840
841 while( c != 0 )
842 {
843 if( i >= X->n )
844 {
845 MPI_CHK( mpi_grow( X, i + 1 ) );
846 p = X->p + i;
847 }
848
Paul Bakker2d319fd2012-09-16 21:34:26 +0000849 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000850 }
851
852cleanup:
853
854 return( ret );
855}
856
857/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100858 * Helper for mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000859 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000860static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000861{
Paul Bakker23986e52011-04-24 08:57:21 +0000862 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000863 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000864
865 for( i = c = 0; i < n; i++, s++, d++ )
866 {
867 z = ( *d < c ); *d -= c;
868 c = ( *d < *s ) + z; *d -= *s;
869 }
870
871 while( c != 0 )
872 {
873 z = ( *d < c ); *d -= c;
874 c = z; i++; d++;
875 }
876}
877
878/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100879 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000880 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000881int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000882{
883 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000884 int ret;
885 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000886
887 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000888 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000889
Paul Bakker6c591fa2011-05-05 11:49:20 +0000890 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000891
892 if( X == B )
893 {
894 MPI_CHK( mpi_copy( &TB, B ) );
895 B = &TB;
896 }
897
898 if( X != A )
899 MPI_CHK( mpi_copy( X, A ) );
900
Paul Bakker1ef7a532009-06-20 10:50:55 +0000901 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100902 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000903 */
904 X->s = 1;
905
Paul Bakker5121ce52009-01-03 21:22:43 +0000906 ret = 0;
907
Paul Bakker23986e52011-04-24 08:57:21 +0000908 for( n = B->n; n > 0; n-- )
909 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000910 break;
911
Paul Bakker23986e52011-04-24 08:57:21 +0000912 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000913
914cleanup:
915
Paul Bakker6c591fa2011-05-05 11:49:20 +0000916 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000917
918 return( ret );
919}
920
921/*
922 * Signed addition: X = A + B
923 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000924int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000925{
926 int ret, s = A->s;
927
928 if( A->s * B->s < 0 )
929 {
930 if( mpi_cmp_abs( A, B ) >= 0 )
931 {
932 MPI_CHK( mpi_sub_abs( X, A, B ) );
933 X->s = s;
934 }
935 else
936 {
937 MPI_CHK( mpi_sub_abs( X, B, A ) );
938 X->s = -s;
939 }
940 }
941 else
942 {
943 MPI_CHK( mpi_add_abs( X, A, B ) );
944 X->s = s;
945 }
946
947cleanup:
948
949 return( ret );
950}
951
952/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100953 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +0000954 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000955int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000956{
957 int ret, s = A->s;
958
959 if( A->s * B->s > 0 )
960 {
961 if( mpi_cmp_abs( A, B ) >= 0 )
962 {
963 MPI_CHK( mpi_sub_abs( X, A, B ) );
964 X->s = s;
965 }
966 else
967 {
968 MPI_CHK( mpi_sub_abs( X, B, A ) );
969 X->s = -s;
970 }
971 }
972 else
973 {
974 MPI_CHK( mpi_add_abs( X, A, B ) );
975 X->s = s;
976 }
977
978cleanup:
979
980 return( ret );
981}
982
983/*
984 * Signed addition: X = A + b
985 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000986int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000987{
988 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +0000989 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000990
991 p[0] = ( b < 0 ) ? -b : b;
992 _B.s = ( b < 0 ) ? -1 : 1;
993 _B.n = 1;
994 _B.p = p;
995
996 return( mpi_add_mpi( X, A, &_B ) );
997}
998
999/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001000 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001001 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001002int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001003{
1004 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001005 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001006
1007 p[0] = ( b < 0 ) ? -b : b;
1008 _B.s = ( b < 0 ) ? -1 : 1;
1009 _B.n = 1;
1010 _B.p = p;
1011
1012 return( mpi_sub_mpi( X, A, &_B ) );
1013}
1014
1015/*
1016 * Helper for mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001017 */
1018static
1019#if defined(__APPLE__) && defined(__arm__)
1020/*
1021 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1022 * appears to need this to prevent bad ARM code generation at -O3.
1023 */
1024__attribute__ ((noinline))
1025#endif
1026void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001027{
Paul Bakkera755ca12011-04-24 09:11:17 +00001028 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001029
1030#if defined(MULADDC_HUIT)
1031 for( ; i >= 8; i -= 8 )
1032 {
1033 MULADDC_INIT
1034 MULADDC_HUIT
1035 MULADDC_STOP
1036 }
1037
1038 for( ; i > 0; i-- )
1039 {
1040 MULADDC_INIT
1041 MULADDC_CORE
1042 MULADDC_STOP
1043 }
1044#else
1045 for( ; i >= 16; i -= 16 )
1046 {
1047 MULADDC_INIT
1048 MULADDC_CORE MULADDC_CORE
1049 MULADDC_CORE MULADDC_CORE
1050 MULADDC_CORE MULADDC_CORE
1051 MULADDC_CORE MULADDC_CORE
1052
1053 MULADDC_CORE MULADDC_CORE
1054 MULADDC_CORE MULADDC_CORE
1055 MULADDC_CORE MULADDC_CORE
1056 MULADDC_CORE MULADDC_CORE
1057 MULADDC_STOP
1058 }
1059
1060 for( ; i >= 8; i -= 8 )
1061 {
1062 MULADDC_INIT
1063 MULADDC_CORE MULADDC_CORE
1064 MULADDC_CORE MULADDC_CORE
1065
1066 MULADDC_CORE MULADDC_CORE
1067 MULADDC_CORE MULADDC_CORE
1068 MULADDC_STOP
1069 }
1070
1071 for( ; i > 0; i-- )
1072 {
1073 MULADDC_INIT
1074 MULADDC_CORE
1075 MULADDC_STOP
1076 }
1077#endif
1078
1079 t++;
1080
1081 do {
1082 *d += c; c = ( *d < c ); d++;
1083 }
1084 while( c != 0 );
1085}
1086
1087/*
1088 * Baseline multiplication: X = A * B (HAC 14.12)
1089 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001090int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001091{
Paul Bakker23986e52011-04-24 08:57:21 +00001092 int ret;
1093 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001094 mpi TA, TB;
1095
Paul Bakker6c591fa2011-05-05 11:49:20 +00001096 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001097
1098 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1099 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1100
Paul Bakker23986e52011-04-24 08:57:21 +00001101 for( i = A->n; i > 0; i-- )
1102 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001103 break;
1104
Paul Bakker23986e52011-04-24 08:57:21 +00001105 for( j = B->n; j > 0; j-- )
1106 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001107 break;
1108
Paul Bakker23986e52011-04-24 08:57:21 +00001109 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001110 MPI_CHK( mpi_lset( X, 0 ) );
1111
Paul Bakker23986e52011-04-24 08:57:21 +00001112 for( i++; j > 0; j-- )
1113 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001114
1115 X->s = A->s * B->s;
1116
1117cleanup:
1118
Paul Bakker6c591fa2011-05-05 11:49:20 +00001119 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001120
1121 return( ret );
1122}
1123
1124/*
1125 * Baseline multiplication: X = A * b
1126 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001127int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001128{
1129 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001130 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001131
1132 _B.s = 1;
1133 _B.n = 1;
1134 _B.p = p;
1135 p[0] = b;
1136
1137 return( mpi_mul_mpi( X, A, &_B ) );
1138}
1139
1140/*
1141 * Division by mpi: A = Q * B + R (HAC 14.20)
1142 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001143int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001144{
Paul Bakker23986e52011-04-24 08:57:21 +00001145 int ret;
1146 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001147 mpi X, Y, Z, T1, T2;
1148
1149 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001150 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001151
Paul Bakker6c591fa2011-05-05 11:49:20 +00001152 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1153 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001154
1155 if( mpi_cmp_abs( A, B ) < 0 )
1156 {
1157 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1158 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1159 return( 0 );
1160 }
1161
1162 MPI_CHK( mpi_copy( &X, A ) );
1163 MPI_CHK( mpi_copy( &Y, B ) );
1164 X.s = Y.s = 1;
1165
1166 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1167 MPI_CHK( mpi_lset( &Z, 0 ) );
1168 MPI_CHK( mpi_grow( &T1, 2 ) );
1169 MPI_CHK( mpi_grow( &T2, 3 ) );
1170
1171 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001172 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001173 {
1174 k = biL - 1 - k;
1175 MPI_CHK( mpi_shift_l( &X, k ) );
1176 MPI_CHK( mpi_shift_l( &Y, k ) );
1177 }
1178 else k = 0;
1179
1180 n = X.n - 1;
1181 t = Y.n - 1;
Paul Bakkerc110d022012-10-19 12:15:08 +00001182 MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001183
1184 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1185 {
1186 Z.p[n - t]++;
1187 mpi_sub_mpi( &X, &X, &Y );
1188 }
1189 mpi_shift_r( &Y, biL * (n - t) );
1190
1191 for( i = n; i > t ; i-- )
1192 {
1193 if( X.p[i] >= Y.p[t] )
1194 Z.p[i - t - 1] = ~0;
1195 else
1196 {
Paul Bakker62261d62012-10-02 12:19:31 +00001197#if defined(POLARSSL_HAVE_UDBL)
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001198 t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001199
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001200 r = (t_udbl) X.p[i] << biL;
1201 r |= (t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001202 r /= Y.p[t];
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001203 if( r > ((t_udbl) 1 << biL) - 1)
1204 r = ((t_udbl) 1 << biL) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001205
Paul Bakkera755ca12011-04-24 09:11:17 +00001206 Z.p[i - t - 1] = (t_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001207#else
1208 /*
1209 * __udiv_qrnnd_c, from gmp/longlong.h
1210 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001211 t_uint q0, q1, r0, r1;
1212 t_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001213
1214 d = Y.p[t];
1215 d0 = ( d << biH ) >> biH;
1216 d1 = ( d >> biH );
1217
1218 q1 = X.p[i] / d1;
1219 r1 = X.p[i] - d1 * q1;
1220 r1 <<= biH;
1221 r1 |= ( X.p[i - 1] >> biH );
1222
1223 m = q1 * d0;
1224 if( r1 < m )
1225 {
1226 q1--, r1 += d;
1227 while( r1 >= d && r1 < m )
1228 q1--, r1 += d;
1229 }
1230 r1 -= m;
1231
1232 q0 = r1 / d1;
1233 r0 = r1 - d1 * q0;
1234 r0 <<= biH;
1235 r0 |= ( X.p[i - 1] << biH ) >> biH;
1236
1237 m = q0 * d0;
1238 if( r0 < m )
1239 {
1240 q0--, r0 += d;
1241 while( r0 >= d && r0 < m )
1242 q0--, r0 += d;
1243 }
1244 r0 -= m;
1245
1246 Z.p[i - t - 1] = ( q1 << biH ) | q0;
1247#endif
1248 }
1249
1250 Z.p[i - t - 1]++;
1251 do
1252 {
1253 Z.p[i - t - 1]--;
1254
1255 MPI_CHK( mpi_lset( &T1, 0 ) );
1256 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1257 T1.p[1] = Y.p[t];
1258 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1259
1260 MPI_CHK( mpi_lset( &T2, 0 ) );
1261 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1262 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1263 T2.p[2] = X.p[i];
1264 }
1265 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1266
1267 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1268 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1269 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1270
1271 if( mpi_cmp_int( &X, 0 ) < 0 )
1272 {
1273 MPI_CHK( mpi_copy( &T1, &Y ) );
1274 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1275 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1276 Z.p[i - t - 1]--;
1277 }
1278 }
1279
1280 if( Q != NULL )
1281 {
1282 mpi_copy( Q, &Z );
1283 Q->s = A->s * B->s;
1284 }
1285
1286 if( R != NULL )
1287 {
1288 mpi_shift_r( &X, k );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001289 X.s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001290 mpi_copy( R, &X );
1291
Paul Bakker5121ce52009-01-03 21:22:43 +00001292 if( mpi_cmp_int( R, 0 ) == 0 )
1293 R->s = 1;
1294 }
1295
1296cleanup:
1297
Paul Bakker6c591fa2011-05-05 11:49:20 +00001298 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1299 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001300
1301 return( ret );
1302}
1303
1304/*
1305 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001306 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001307int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001308{
1309 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001310 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001311
1312 p[0] = ( b < 0 ) ? -b : b;
1313 _B.s = ( b < 0 ) ? -1 : 1;
1314 _B.n = 1;
1315 _B.p = p;
1316
1317 return( mpi_div_mpi( Q, R, A, &_B ) );
1318}
1319
1320/*
1321 * Modulo: R = A mod B
1322 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001323int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001324{
1325 int ret;
1326
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001327 if( mpi_cmp_int( B, 0 ) < 0 )
1328 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1329
Paul Bakker5121ce52009-01-03 21:22:43 +00001330 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1331
1332 while( mpi_cmp_int( R, 0 ) < 0 )
1333 MPI_CHK( mpi_add_mpi( R, R, B ) );
1334
1335 while( mpi_cmp_mpi( R, B ) >= 0 )
1336 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1337
1338cleanup:
1339
1340 return( ret );
1341}
1342
1343/*
1344 * Modulo: r = A mod b
1345 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001346int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001347{
Paul Bakker23986e52011-04-24 08:57:21 +00001348 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001349 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001350
1351 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001352 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001353
1354 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001355 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001356
1357 /*
1358 * handle trivial cases
1359 */
1360 if( b == 1 )
1361 {
1362 *r = 0;
1363 return( 0 );
1364 }
1365
1366 if( b == 2 )
1367 {
1368 *r = A->p[0] & 1;
1369 return( 0 );
1370 }
1371
1372 /*
1373 * general case
1374 */
Paul Bakker23986e52011-04-24 08:57:21 +00001375 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001376 {
Paul Bakker23986e52011-04-24 08:57:21 +00001377 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001378 y = ( y << biH ) | ( x >> biH );
1379 z = y / b;
1380 y -= z * b;
1381
1382 x <<= biH;
1383 y = ( y << biH ) | ( x >> biH );
1384 z = y / b;
1385 y -= z * b;
1386 }
1387
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001388 /*
1389 * If A is negative, then the current y represents a negative value.
1390 * Flipping it to the positive side.
1391 */
1392 if( A->s < 0 && y != 0 )
1393 y = b - y;
1394
Paul Bakker5121ce52009-01-03 21:22:43 +00001395 *r = y;
1396
1397 return( 0 );
1398}
1399
1400/*
1401 * Fast Montgomery initialization (thanks to Tom St Denis)
1402 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001403static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001404{
Paul Bakkera755ca12011-04-24 09:11:17 +00001405 t_uint x, m0 = N->p[0];
Paul Bakker5121ce52009-01-03 21:22:43 +00001406
1407 x = m0;
1408 x += ( ( m0 + 2 ) & 4 ) << 1;
1409 x *= ( 2 - ( m0 * x ) );
1410
1411 if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
1412 if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
1413 if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
1414
1415 *mm = ~x + 1;
1416}
1417
1418/*
1419 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1420 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001421static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001422{
Paul Bakker23986e52011-04-24 08:57:21 +00001423 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001424 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001425
1426 memset( T->p, 0, T->n * ciL );
1427
1428 d = T->p;
1429 n = N->n;
1430 m = ( B->n < n ) ? B->n : n;
1431
1432 for( i = 0; i < n; i++ )
1433 {
1434 /*
1435 * T = (T + u0*B + u1*N) / 2^biL
1436 */
1437 u0 = A->p[i];
1438 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1439
1440 mpi_mul_hlp( m, B->p, d, u0 );
1441 mpi_mul_hlp( n, N->p, d, u1 );
1442
1443 *d++ = u0; d[n + 1] = 0;
1444 }
1445
1446 memcpy( A->p, d, (n + 1) * ciL );
1447
1448 if( mpi_cmp_abs( A, N ) >= 0 )
1449 mpi_sub_hlp( n, N->p, A->p );
1450 else
1451 /* prevent timing attacks */
1452 mpi_sub_hlp( n, A->p, T->p );
1453}
1454
1455/*
1456 * Montgomery reduction: A = A * R^-1 mod N
1457 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001458static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001459{
Paul Bakkera755ca12011-04-24 09:11:17 +00001460 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001461 mpi U;
1462
Paul Bakker8ddb6452013-02-27 14:56:33 +01001463 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001464 U.p = &z;
1465
1466 mpi_montmul( A, &U, N, mm, T );
1467}
1468
1469/*
1470 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1471 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001472int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001473{
Paul Bakker23986e52011-04-24 08:57:21 +00001474 int ret;
1475 size_t wbits, wsize, one = 1;
1476 size_t i, j, nblimbs;
1477 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001478 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001479 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1480 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001481
1482 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001483 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001484
Paul Bakkerf6198c12012-05-16 08:02:29 +00001485 if( mpi_cmp_int( E, 0 ) < 0 )
1486 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1487
1488 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001489 * Init temps and window size
1490 */
1491 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001492 mpi_init( &RR ); mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001493 memset( W, 0, sizeof( W ) );
1494
1495 i = mpi_msb( E );
1496
1497 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1498 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1499
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001500 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1501 wsize = POLARSSL_MPI_WINDOW_SIZE;
1502
Paul Bakker5121ce52009-01-03 21:22:43 +00001503 j = N->n + 1;
1504 MPI_CHK( mpi_grow( X, j ) );
1505 MPI_CHK( mpi_grow( &W[1], j ) );
1506 MPI_CHK( mpi_grow( &T, j * 2 ) );
1507
1508 /*
Paul Bakker50546922012-05-19 08:40:49 +00001509 * Compensate for negative A (and correct at the end)
1510 */
1511 neg = ( A->s == -1 );
1512
1513 mpi_init( &Apos );
1514 if( neg )
1515 {
1516 MPI_CHK( mpi_copy( &Apos, A ) );
1517 Apos.s = 1;
1518 A = &Apos;
1519 }
1520
1521 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001522 * If 1st call, pre-compute R^2 mod N
1523 */
1524 if( _RR == NULL || _RR->p == NULL )
1525 {
1526 MPI_CHK( mpi_lset( &RR, 1 ) );
1527 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1528 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1529
1530 if( _RR != NULL )
1531 memcpy( _RR, &RR, sizeof( mpi ) );
1532 }
1533 else
1534 memcpy( &RR, _RR, sizeof( mpi ) );
1535
1536 /*
1537 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1538 */
1539 if( mpi_cmp_mpi( A, N ) >= 0 )
1540 mpi_mod_mpi( &W[1], A, N );
1541 else mpi_copy( &W[1], A );
1542
1543 mpi_montmul( &W[1], &RR, N, mm, &T );
1544
1545 /*
1546 * X = R^2 * R^-1 mod N = R mod N
1547 */
1548 MPI_CHK( mpi_copy( X, &RR ) );
1549 mpi_montred( X, N, mm, &T );
1550
1551 if( wsize > 1 )
1552 {
1553 /*
1554 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1555 */
Paul Bakker23986e52011-04-24 08:57:21 +00001556 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001557
1558 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1559 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1560
1561 for( i = 0; i < wsize - 1; i++ )
1562 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001563
Paul Bakker5121ce52009-01-03 21:22:43 +00001564 /*
1565 * W[i] = W[i - 1] * W[1]
1566 */
Paul Bakker23986e52011-04-24 08:57:21 +00001567 for( i = j + 1; i < (one << wsize); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001568 {
1569 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1570 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1571
1572 mpi_montmul( &W[i], &W[1], N, mm, &T );
1573 }
1574 }
1575
1576 nblimbs = E->n;
1577 bufsize = 0;
1578 nbits = 0;
1579 wbits = 0;
1580 state = 0;
1581
1582 while( 1 )
1583 {
1584 if( bufsize == 0 )
1585 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001586 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001587 break;
1588
Paul Bakker0d7702c2013-10-29 16:18:35 +01001589 nblimbs--;
1590
Paul Bakkera755ca12011-04-24 09:11:17 +00001591 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001592 }
1593
1594 bufsize--;
1595
1596 ei = (E->p[nblimbs] >> bufsize) & 1;
1597
1598 /*
1599 * skip leading 0s
1600 */
1601 if( ei == 0 && state == 0 )
1602 continue;
1603
1604 if( ei == 0 && state == 1 )
1605 {
1606 /*
1607 * out of window, square X
1608 */
1609 mpi_montmul( X, X, N, mm, &T );
1610 continue;
1611 }
1612
1613 /*
1614 * add ei to current window
1615 */
1616 state = 2;
1617
1618 nbits++;
1619 wbits |= (ei << (wsize - nbits));
1620
1621 if( nbits == wsize )
1622 {
1623 /*
1624 * X = X^wsize R^-1 mod N
1625 */
1626 for( i = 0; i < wsize; i++ )
1627 mpi_montmul( X, X, N, mm, &T );
1628
1629 /*
1630 * X = X * W[wbits] R^-1 mod N
1631 */
1632 mpi_montmul( X, &W[wbits], N, mm, &T );
1633
1634 state--;
1635 nbits = 0;
1636 wbits = 0;
1637 }
1638 }
1639
1640 /*
1641 * process the remaining bits
1642 */
1643 for( i = 0; i < nbits; i++ )
1644 {
1645 mpi_montmul( X, X, N, mm, &T );
1646
1647 wbits <<= 1;
1648
Paul Bakker23986e52011-04-24 08:57:21 +00001649 if( (wbits & (one << wsize)) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001650 mpi_montmul( X, &W[1], N, mm, &T );
1651 }
1652
1653 /*
1654 * X = A^E * R * R^-1 mod N = A^E mod N
1655 */
1656 mpi_montred( X, N, mm, &T );
1657
Paul Bakkerf6198c12012-05-16 08:02:29 +00001658 if( neg )
1659 {
1660 X->s = -1;
1661 mpi_add_mpi( X, N, X );
1662 }
1663
Paul Bakker5121ce52009-01-03 21:22:43 +00001664cleanup:
1665
Paul Bakker23986e52011-04-24 08:57:21 +00001666 for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001667 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001668
Paul Bakkerf6198c12012-05-16 08:02:29 +00001669 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001670
1671 if( _RR == NULL )
1672 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001673
1674 return( ret );
1675}
1676
Paul Bakker5121ce52009-01-03 21:22:43 +00001677/*
1678 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1679 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001680int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001681{
Paul Bakker23986e52011-04-24 08:57:21 +00001682 int ret;
1683 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001684 mpi TG, TA, TB;
1685
Paul Bakker6c591fa2011-05-05 11:49:20 +00001686 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001687
Paul Bakker5121ce52009-01-03 21:22:43 +00001688 MPI_CHK( mpi_copy( &TA, A ) );
1689 MPI_CHK( mpi_copy( &TB, B ) );
1690
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001691 lz = mpi_lsb( &TA );
1692 lzt = mpi_lsb( &TB );
1693
1694 if ( lzt < lz )
1695 lz = lzt;
1696
1697 MPI_CHK( mpi_shift_r( &TA, lz ) );
1698 MPI_CHK( mpi_shift_r( &TB, lz ) );
1699
Paul Bakker5121ce52009-01-03 21:22:43 +00001700 TA.s = TB.s = 1;
1701
1702 while( mpi_cmp_int( &TA, 0 ) != 0 )
1703 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001704 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1705 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001706
1707 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1708 {
1709 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1710 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1711 }
1712 else
1713 {
1714 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1715 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1716 }
1717 }
1718
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001719 MPI_CHK( mpi_shift_l( &TB, lz ) );
1720 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001721
1722cleanup:
1723
Paul Bakker6c591fa2011-05-05 11:49:20 +00001724 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001725
1726 return( ret );
1727}
1728
Paul Bakkera3d195c2011-11-27 21:07:34 +00001729int mpi_fill_random( mpi *X, size_t size,
1730 int (*f_rng)(void *, unsigned char *, size_t),
1731 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001732{
Paul Bakker23986e52011-04-24 08:57:21 +00001733 int ret;
Paul Bakker287781a2011-03-26 13:18:49 +00001734
Paul Bakker39dfdac2012-02-12 17:17:27 +00001735 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001736 MPI_CHK( mpi_lset( X, 0 ) );
1737
Paul Bakker39dfdac2012-02-12 17:17:27 +00001738 MPI_CHK( f_rng( p_rng, (unsigned char *) X->p, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001739
1740cleanup:
1741 return( ret );
1742}
1743
Paul Bakker5121ce52009-01-03 21:22:43 +00001744/*
1745 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1746 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001747int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001748{
1749 int ret;
1750 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1751
1752 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001753 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001754
Paul Bakker6c591fa2011-05-05 11:49:20 +00001755 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1756 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1757 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001758
1759 MPI_CHK( mpi_gcd( &G, A, N ) );
1760
1761 if( mpi_cmp_int( &G, 1 ) != 0 )
1762 {
Paul Bakker40e46942009-01-03 21:51:57 +00001763 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001764 goto cleanup;
1765 }
1766
1767 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1768 MPI_CHK( mpi_copy( &TU, &TA ) );
1769 MPI_CHK( mpi_copy( &TB, N ) );
1770 MPI_CHK( mpi_copy( &TV, N ) );
1771
1772 MPI_CHK( mpi_lset( &U1, 1 ) );
1773 MPI_CHK( mpi_lset( &U2, 0 ) );
1774 MPI_CHK( mpi_lset( &V1, 0 ) );
1775 MPI_CHK( mpi_lset( &V2, 1 ) );
1776
1777 do
1778 {
1779 while( ( TU.p[0] & 1 ) == 0 )
1780 {
1781 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1782
1783 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1784 {
1785 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1786 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1787 }
1788
1789 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1790 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1791 }
1792
1793 while( ( TV.p[0] & 1 ) == 0 )
1794 {
1795 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1796
1797 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1798 {
1799 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1800 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1801 }
1802
1803 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1804 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1805 }
1806
1807 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1808 {
1809 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1810 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1811 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1812 }
1813 else
1814 {
1815 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1816 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1817 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1818 }
1819 }
1820 while( mpi_cmp_int( &TU, 0 ) != 0 );
1821
1822 while( mpi_cmp_int( &V1, 0 ) < 0 )
1823 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1824
1825 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1826 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1827
1828 MPI_CHK( mpi_copy( X, &V1 ) );
1829
1830cleanup:
1831
Paul Bakker6c591fa2011-05-05 11:49:20 +00001832 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1833 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1834 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001835
1836 return( ret );
1837}
1838
Paul Bakkerd9374b02012-11-02 11:02:58 +00001839#if defined(POLARSSL_GENPRIME)
1840
Paul Bakker5121ce52009-01-03 21:22:43 +00001841static const int small_prime[] =
1842{
1843 3, 5, 7, 11, 13, 17, 19, 23,
1844 29, 31, 37, 41, 43, 47, 53, 59,
1845 61, 67, 71, 73, 79, 83, 89, 97,
1846 101, 103, 107, 109, 113, 127, 131, 137,
1847 139, 149, 151, 157, 163, 167, 173, 179,
1848 181, 191, 193, 197, 199, 211, 223, 227,
1849 229, 233, 239, 241, 251, 257, 263, 269,
1850 271, 277, 281, 283, 293, 307, 311, 313,
1851 317, 331, 337, 347, 349, 353, 359, 367,
1852 373, 379, 383, 389, 397, 401, 409, 419,
1853 421, 431, 433, 439, 443, 449, 457, 461,
1854 463, 467, 479, 487, 491, 499, 503, 509,
1855 521, 523, 541, 547, 557, 563, 569, 571,
1856 577, 587, 593, 599, 601, 607, 613, 617,
1857 619, 631, 641, 643, 647, 653, 659, 661,
1858 673, 677, 683, 691, 701, 709, 719, 727,
1859 733, 739, 743, 751, 757, 761, 769, 773,
1860 787, 797, 809, 811, 821, 823, 827, 829,
1861 839, 853, 857, 859, 863, 877, 881, 883,
1862 887, 907, 911, 919, 929, 937, 941, 947,
1863 953, 967, 971, 977, 983, 991, 997, -103
1864};
1865
1866/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001867 * Small divisors test (X must be positive)
1868 *
1869 * Return values:
1870 * 0: no small factor (possible prime, more tests needed)
1871 * 1: certain prime
1872 * POLARSSL_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
1873 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00001874 */
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001875static int mpi_check_small_factors( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00001876{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001877 int ret = 0;
1878 size_t i;
1879 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001880
Paul Bakker5121ce52009-01-03 21:22:43 +00001881 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001882 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001883
1884 for( i = 0; small_prime[i] > 0; i++ )
1885 {
Paul Bakker5121ce52009-01-03 21:22:43 +00001886 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001887 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001888
1889 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1890
1891 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001892 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001893 }
1894
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001895cleanup:
1896 return( ret );
1897}
1898
1899/*
1900 * Miller-Rabin pseudo-primality test (HAC 4.24)
1901 */
1902static int mpi_miller_rabin( const mpi *X,
1903 int (*f_rng)(void *, unsigned char *, size_t),
1904 void *p_rng )
1905{
1906 int ret;
1907 size_t i, j, n, s;
1908 mpi W, R, T, A, RR;
1909
1910 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
1911 mpi_init( &RR );
1912
Paul Bakker5121ce52009-01-03 21:22:43 +00001913 /*
1914 * W = |X| - 1
1915 * R = W >> lsb( W )
1916 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001917 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001918 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001919 MPI_CHK( mpi_copy( &R, &W ) );
1920 MPI_CHK( mpi_shift_r( &R, s ) );
1921
1922 i = mpi_msb( X );
1923 /*
1924 * HAC, table 4.4
1925 */
1926 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1927 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1928 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1929
1930 for( i = 0; i < n; i++ )
1931 {
1932 /*
1933 * pick a random A, 1 < A < |X| - 1
1934 */
Paul Bakker901c6562012-04-20 13:25:38 +00001935 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001936
Paul Bakkerb94081b2011-01-05 15:53:06 +00001937 if( mpi_cmp_mpi( &A, &W ) >= 0 )
1938 {
1939 j = mpi_msb( &A ) - mpi_msb( &W );
1940 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1941 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001942 A.p[0] |= 3;
1943
1944 /*
1945 * A = A^R mod |X|
1946 */
1947 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1948
1949 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1950 mpi_cmp_int( &A, 1 ) == 0 )
1951 continue;
1952
1953 j = 1;
1954 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1955 {
1956 /*
1957 * A = A * A mod |X|
1958 */
1959 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1960 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1961
1962 if( mpi_cmp_int( &A, 1 ) == 0 )
1963 break;
1964
1965 j++;
1966 }
1967
1968 /*
1969 * not prime if A != |X| - 1 or A == 1
1970 */
1971 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1972 mpi_cmp_int( &A, 1 ) == 0 )
1973 {
Paul Bakker40e46942009-01-03 21:51:57 +00001974 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001975 break;
1976 }
1977 }
1978
1979cleanup:
Paul Bakker6c591fa2011-05-05 11:49:20 +00001980 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
1981 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001982
1983 return( ret );
1984}
1985
1986/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001987 * Pseudo-primality test: small factors, then Miller-Rabin
1988 */
Paul Bakker45f457d2013-11-25 14:26:52 +01001989int mpi_is_prime( mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001990 int (*f_rng)(void *, unsigned char *, size_t),
1991 void *p_rng )
1992{
1993 int ret;
1994 const mpi XX = { 1, X->n, X->p }; /* Abs(X) */
1995
1996 if( mpi_cmp_int( &XX, 0 ) == 0 ||
1997 mpi_cmp_int( &XX, 1 ) == 0 )
1998 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1999
2000 if( mpi_cmp_int( &XX, 2 ) == 0 )
2001 return( 0 );
2002
2003 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2004 {
2005 if( ret == 1 )
2006 return( 0 );
2007
2008 return( ret );
2009 }
2010
2011 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2012}
2013
2014/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002015 * Prime number generation
2016 */
Paul Bakker23986e52011-04-24 08:57:21 +00002017int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002018 int (*f_rng)(void *, unsigned char *, size_t),
2019 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002020{
Paul Bakker23986e52011-04-24 08:57:21 +00002021 int ret;
2022 size_t k, n;
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002023 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002024 mpi Y;
2025
Paul Bakkerfe3256e2011-11-25 12:11:43 +00002026 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00002027 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002028
Paul Bakker6c591fa2011-05-05 11:49:20 +00002029 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002030
2031 n = BITS_TO_LIMBS( nbits );
2032
Paul Bakker901c6562012-04-20 13:25:38 +00002033 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002034
2035 k = mpi_msb( X );
2036 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
2037 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
2038
2039 X->p[0] |= 3;
2040
2041 if( dh_flag == 0 )
2042 {
2043 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
2044 {
Paul Bakker40e46942009-01-03 21:51:57 +00002045 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002046 goto cleanup;
2047
2048 MPI_CHK( mpi_add_int( X, X, 2 ) );
2049 }
2050 }
2051 else
2052 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002053 /*
2054 * An necessary condition for Y and X = 2Y + 1 to be prime
2055 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2056 * Make sure it is satisfied, while keeping X = 3 mod 4
2057 */
2058 MPI_CHK( mpi_mod_int( &r, X, 3 ) );
2059 if( r == 0 )
2060 MPI_CHK( mpi_add_int( X, X, 8 ) );
2061 else if( r == 1 )
2062 MPI_CHK( mpi_add_int( X, X, 4 ) );
2063
2064 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2065 MPI_CHK( mpi_copy( &Y, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002066 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2067
2068 while( 1 )
2069 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002070 /*
2071 * First, check small factors for X and Y
2072 * before doing Miller-Rabin on any of them
2073 */
2074 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2075 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2076 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2077 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002078 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002079 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002080 }
2081
Paul Bakker40e46942009-01-03 21:51:57 +00002082 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002083 goto cleanup;
2084
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002085 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002086 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002087 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2088 * so up Y by 6 and X by 12.
2089 */
2090 MPI_CHK( mpi_add_int( X, X, 12 ) );
2091 MPI_CHK( mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002092 }
2093 }
2094
2095cleanup:
2096
Paul Bakker6c591fa2011-05-05 11:49:20 +00002097 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002098
2099 return( ret );
2100}
2101
Manuel Pégourié-Gonnarddf0142b2013-08-22 18:29:07 +02002102#endif /* POLARSSL_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002103
Paul Bakker40e46942009-01-03 21:51:57 +00002104#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002105
Paul Bakker23986e52011-04-24 08:57:21 +00002106#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002107
2108static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2109{
2110 { 693, 609, 21 },
2111 { 1764, 868, 28 },
2112 { 768454923, 542167814, 1 }
2113};
2114
Paul Bakker5121ce52009-01-03 21:22:43 +00002115/*
2116 * Checkup routine
2117 */
2118int mpi_self_test( int verbose )
2119{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002120 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002121 mpi A, E, N, X, Y, U, V;
2122
Paul Bakker6c591fa2011-05-05 11:49:20 +00002123 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2124 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002125
2126 MPI_CHK( mpi_read_string( &A, 16,
2127 "EFE021C2645FD1DC586E69184AF4A31E" \
2128 "D5F53E93B5F123FA41680867BA110131" \
2129 "944FE7952E2517337780CB0DB80E61AA" \
2130 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2131
2132 MPI_CHK( mpi_read_string( &E, 16,
2133 "B2E7EFD37075B9F03FF989C7C5051C20" \
2134 "34D2A323810251127E7BF8625A4F49A5" \
2135 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2136 "5B5C25763222FEFCCFC38B832366C29E" ) );
2137
2138 MPI_CHK( mpi_read_string( &N, 16,
2139 "0066A198186C18C10B2F5ED9B522752A" \
2140 "9830B69916E535C8F047518A889A43A5" \
2141 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2142
2143 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2144
2145 MPI_CHK( mpi_read_string( &U, 16,
2146 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2147 "9E857EA95A03512E2BAE7391688D264A" \
2148 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2149 "8001B72E848A38CAE1C65F78E56ABDEF" \
2150 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2151 "ECF677152EF804370C1A305CAF3B5BF1" \
2152 "30879B56C61DE584A0F53A2447A51E" ) );
2153
2154 if( verbose != 0 )
2155 printf( " MPI test #1 (mul_mpi): " );
2156
2157 if( mpi_cmp_mpi( &X, &U ) != 0 )
2158 {
2159 if( verbose != 0 )
2160 printf( "failed\n" );
2161
2162 return( 1 );
2163 }
2164
2165 if( verbose != 0 )
2166 printf( "passed\n" );
2167
2168 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2169
2170 MPI_CHK( mpi_read_string( &U, 16,
2171 "256567336059E52CAE22925474705F39A94" ) );
2172
2173 MPI_CHK( mpi_read_string( &V, 16,
2174 "6613F26162223DF488E9CD48CC132C7A" \
2175 "0AC93C701B001B092E4E5B9F73BCD27B" \
2176 "9EE50D0657C77F374E903CDFA4C642" ) );
2177
2178 if( verbose != 0 )
2179 printf( " MPI test #2 (div_mpi): " );
2180
2181 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2182 mpi_cmp_mpi( &Y, &V ) != 0 )
2183 {
2184 if( verbose != 0 )
2185 printf( "failed\n" );
2186
2187 return( 1 );
2188 }
2189
2190 if( verbose != 0 )
2191 printf( "passed\n" );
2192
2193 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2194
2195 MPI_CHK( mpi_read_string( &U, 16,
2196 "36E139AEA55215609D2816998ED020BB" \
2197 "BD96C37890F65171D948E9BC7CBAA4D9" \
2198 "325D24D6A3C12710F10A09FA08AB87" ) );
2199
2200 if( verbose != 0 )
2201 printf( " MPI test #3 (exp_mod): " );
2202
2203 if( mpi_cmp_mpi( &X, &U ) != 0 )
2204 {
2205 if( verbose != 0 )
2206 printf( "failed\n" );
2207
2208 return( 1 );
2209 }
2210
2211 if( verbose != 0 )
2212 printf( "passed\n" );
2213
2214 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2215
2216 MPI_CHK( mpi_read_string( &U, 16,
2217 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2218 "C3DBA76456363A10869622EAC2DD84EC" \
2219 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2220
2221 if( verbose != 0 )
2222 printf( " MPI test #4 (inv_mod): " );
2223
2224 if( mpi_cmp_mpi( &X, &U ) != 0 )
2225 {
2226 if( verbose != 0 )
2227 printf( "failed\n" );
2228
2229 return( 1 );
2230 }
2231
2232 if( verbose != 0 )
2233 printf( "passed\n" );
2234
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002235 if( verbose != 0 )
2236 printf( " MPI test #5 (simple gcd): " );
2237
2238 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2239 {
2240 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002241 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002242
Paul Bakker23986e52011-04-24 08:57:21 +00002243 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002244
Paul Bakker23986e52011-04-24 08:57:21 +00002245 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2246 {
2247 if( verbose != 0 )
2248 printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002249
Paul Bakker23986e52011-04-24 08:57:21 +00002250 return( 1 );
2251 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002252 }
2253
2254 if( verbose != 0 )
2255 printf( "passed\n" );
2256
Paul Bakker5121ce52009-01-03 21:22:43 +00002257cleanup:
2258
2259 if( ret != 0 && verbose != 0 )
2260 printf( "Unexpected error, return code = %08X\n", ret );
2261
Paul Bakker6c591fa2011-05-05 11:49:20 +00002262 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2263 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002264
2265 if( verbose != 0 )
2266 printf( "\n" );
2267
2268 return( ret );
2269}
2270
2271#endif
2272
2273#endif