blob: b606238c372fa38a45aa98ad835ab8d241e07a11 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
Paul Bakkerb96f1542010-07-18 20:36:00 +00005 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +00006 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakkerb96f1542010-07-18 20:36:00 +00007 *
Paul Bakker5121ce52009-01-03 21:22:43 +00008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
Simon Butchere4ed3472015-12-22 15:26:57 +000022
Paul Bakker5121ce52009-01-03 21:22:43 +000023/*
Simon Butchere4ed3472015-12-22 15:26:57 +000024 * The following sources were referenced in the design of this Multi-precision
25 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000026 *
Simon Butchere4ed3472015-12-22 15:26:57 +000027 * [1] Handbook of Applied Cryptography - 1997
28 * Menezes, van Oorschot and Vanstone
29 *
30 * [2] Multi-Precision Math
31 * Tom St Denis
32 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
33 *
34 * [3] GNU Multi-Precision Arithmetic Library
35 * https://gmplib.org/manual/index.html
36 *
Simon Butcher14400c82016-01-02 00:08:13 +000037 */
Paul Bakker5121ce52009-01-03 21:22:43 +000038
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020039#if !defined(POLARSSL_CONFIG_FILE)
Paul Bakker40e46942009-01-03 21:51:57 +000040#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020041#else
42#include POLARSSL_CONFIG_FILE
43#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000044
Paul Bakker40e46942009-01-03 21:51:57 +000045#if defined(POLARSSL_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000046
Paul Bakker40e46942009-01-03 21:51:57 +000047#include "polarssl/bignum.h"
48#include "polarssl/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000049
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <string.h>
51
Paul Bakker7dc4c442014-02-01 22:50:26 +010052#if defined(POLARSSL_PLATFORM_C)
53#include "polarssl/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020054#else
Rich Evans00ab4702015-02-06 13:43:58 +000055#include <stdio.h>
56#include <stdlib.h>
Paul Bakker7dc4c442014-02-01 22:50:26 +010057#define polarssl_printf printf
Paul Bakker6e339b52013-07-03 13:37:05 +020058#define polarssl_malloc malloc
59#define polarssl_free free
60#endif
61
Paul Bakker34617722014-06-13 17:20:13 +020062/* Implementation that should never be optimized out by the compiler */
63static void polarssl_zeroize( void *v, size_t n ) {
64 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
65}
66
Paul Bakkerf9688572011-05-05 10:00:45 +000067#define ciL (sizeof(t_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000068#define biL (ciL << 3) /* bits in limb */
69#define biH (ciL << 2) /* half limb size */
70
Manuel Pégourié-Gonnardfa647a72015-10-05 15:23:11 +010071#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
72
Paul Bakker5121ce52009-01-03 21:22:43 +000073/*
74 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard59efb6a2015-09-28 13:48:04 +020075 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000076 */
Manuel Pégourié-Gonnard59efb6a2015-09-28 13:48:04 +020077#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
78#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000079
80/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000081 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000082 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000083void mpi_init( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000084{
Paul Bakker6c591fa2011-05-05 11:49:20 +000085 if( X == NULL )
86 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000087
Paul Bakker6c591fa2011-05-05 11:49:20 +000088 X->s = 1;
89 X->n = 0;
90 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000091}
92
93/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000094 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000095 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000096void mpi_free( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000097{
Paul Bakker6c591fa2011-05-05 11:49:20 +000098 if( X == NULL )
99 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000100
Paul Bakker6c591fa2011-05-05 11:49:20 +0000101 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102 {
Paul Bakker34617722014-06-13 17:20:13 +0200103 polarssl_zeroize( X->p, X->n * ciL );
Paul Bakker6e339b52013-07-03 13:37:05 +0200104 polarssl_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000105 }
106
Paul Bakker6c591fa2011-05-05 11:49:20 +0000107 X->s = 1;
108 X->n = 0;
109 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000110}
111
112/*
113 * Enlarge to the specified number of limbs
114 */
Paul Bakker23986e52011-04-24 08:57:21 +0000115int mpi_grow( mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000116{
Paul Bakkera755ca12011-04-24 09:11:17 +0000117 t_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000118
Paul Bakkerf9688572011-05-05 10:00:45 +0000119 if( nblimbs > POLARSSL_MPI_MAX_LIMBS )
Paul Bakker69e095c2011-12-10 21:55:01 +0000120 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000121
Paul Bakker5121ce52009-01-03 21:22:43 +0000122 if( X->n < nblimbs )
123 {
Mansour Moufidc531b4a2015-02-15 17:35:38 -0500124 if( ( p = polarssl_malloc( nblimbs * ciL ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000125 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000126
127 memset( p, 0, nblimbs * ciL );
128
129 if( X->p != NULL )
130 {
131 memcpy( p, X->p, X->n * ciL );
Paul Bakker34617722014-06-13 17:20:13 +0200132 polarssl_zeroize( X->p, X->n * ciL );
Paul Bakker6e339b52013-07-03 13:37:05 +0200133 polarssl_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000134 }
135
136 X->n = nblimbs;
137 X->p = p;
138 }
139
140 return( 0 );
141}
142
143/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100144 * Resize down as much as possible,
145 * while keeping at least the specified number of limbs
146 */
147int mpi_shrink( mpi *X, size_t nblimbs )
148{
149 t_uint *p;
150 size_t i;
151
152 /* Actually resize up in this case */
153 if( X->n <= nblimbs )
154 return( mpi_grow( X, nblimbs ) );
155
156 for( i = X->n - 1; i > 0; i-- )
157 if( X->p[i] != 0 )
158 break;
159 i++;
160
161 if( i < nblimbs )
162 i = nblimbs;
163
Mansour Moufidc531b4a2015-02-15 17:35:38 -0500164 if( ( p = polarssl_malloc( i * ciL ) ) == NULL )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100165 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
166
167 memset( p, 0, i * ciL );
168
169 if( X->p != NULL )
170 {
171 memcpy( p, X->p, i * ciL );
Paul Bakker34617722014-06-13 17:20:13 +0200172 polarssl_zeroize( X->p, X->n * ciL );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100173 polarssl_free( X->p );
174 }
175
176 X->n = i;
177 X->p = p;
178
179 return( 0 );
180}
181
182/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000183 * Copy the contents of Y into X
184 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000185int mpi_copy( mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000186{
Paul Bakker23986e52011-04-24 08:57:21 +0000187 int ret;
188 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000189
190 if( X == Y )
191 return( 0 );
192
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200193 if( Y->p == NULL )
194 {
195 mpi_free( X );
196 return( 0 );
197 }
198
Paul Bakker5121ce52009-01-03 21:22:43 +0000199 for( i = Y->n - 1; i > 0; i-- )
200 if( Y->p[i] != 0 )
201 break;
202 i++;
203
204 X->s = Y->s;
205
206 MPI_CHK( mpi_grow( X, i ) );
207
208 memset( X->p, 0, X->n * ciL );
209 memcpy( X->p, Y->p, i * ciL );
210
211cleanup:
212
213 return( ret );
214}
215
216/*
217 * Swap the contents of X and Y
218 */
219void mpi_swap( mpi *X, mpi *Y )
220{
221 mpi T;
222
223 memcpy( &T, X, sizeof( mpi ) );
224 memcpy( X, Y, sizeof( mpi ) );
225 memcpy( Y, &T, sizeof( mpi ) );
226}
227
228/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100229 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100230 * about whether the assignment was made or not.
231 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100232 */
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100233int mpi_safe_cond_assign( mpi *X, const mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100234{
235 int ret = 0;
236 size_t i;
237
Pascal Junodb99183d2015-03-11 16:49:45 +0100238 /* make sure assign is 0 or 1 in a time-constant manner */
239 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100240
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100241 MPI_CHK( mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100242
Paul Bakker66d5d072014-06-17 16:39:18 +0200243 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100244
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100245 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200246 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100247
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100248 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200249 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250
251cleanup:
252 return( ret );
253}
254
255/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100256 * Conditionally swap X and Y, without leaking information
257 * about whether the swap was made or not.
258 * Here it is not ok to simply swap the pointers, which whould lead to
259 * different memory access patterns when X and Y are used afterwards.
260 */
261int mpi_safe_cond_swap( mpi *X, mpi *Y, unsigned char swap )
262{
263 int ret, s;
264 size_t i;
265 t_uint tmp;
266
267 if( X == Y )
268 return( 0 );
269
Pascal Junodb99183d2015-03-11 16:49:45 +0100270 /* make sure swap is 0 or 1 in a time-constant manner */
271 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100272
273 MPI_CHK( mpi_grow( X, Y->n ) );
274 MPI_CHK( mpi_grow( Y, X->n ) );
275
276 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200277 X->s = X->s * ( 1 - swap ) + Y->s * swap;
278 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100279
280
281 for( i = 0; i < X->n; i++ )
282 {
283 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200284 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
285 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286 }
287
288cleanup:
289 return( ret );
290}
291
292/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000293 * Set value from integer
294 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000295int mpi_lset( mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000296{
297 int ret;
298
299 MPI_CHK( mpi_grow( X, 1 ) );
300 memset( X->p, 0, X->n * ciL );
301
302 X->p[0] = ( z < 0 ) ? -z : z;
303 X->s = ( z < 0 ) ? -1 : 1;
304
305cleanup:
306
307 return( ret );
308}
309
310/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000311 * Get a specific bit
312 */
Paul Bakker6b906e52012-05-08 12:01:43 +0000313int mpi_get_bit( const mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000314{
315 if( X->n * biL <= pos )
316 return( 0 );
317
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200318 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000319}
320
321/*
322 * Set a bit to a specific value of 0 or 1
323 */
324int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
325{
326 int ret = 0;
327 size_t off = pos / biL;
328 size_t idx = pos % biL;
329
330 if( val != 0 && val != 1 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200331 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200332
Paul Bakker2f5947e2011-05-18 15:47:11 +0000333 if( X->n * biL <= pos )
334 {
335 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200336 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000337
338 MPI_CHK( mpi_grow( X, off + 1 ) );
339 }
340
Manuel Pégourié-Gonnard9a4a5ac2013-12-04 18:05:29 +0100341 X->p[off] &= ~( (t_uint) 0x01 << idx );
342 X->p[off] |= (t_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000343
344cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200345
Paul Bakker2f5947e2011-05-18 15:47:11 +0000346 return( ret );
347}
348
349/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000350 * Return the number of least significant bits
351 */
Paul Bakker23986e52011-04-24 08:57:21 +0000352size_t mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000353{
Paul Bakker23986e52011-04-24 08:57:21 +0000354 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000355
356 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000357 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000358 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
359 return( count );
360
361 return( 0 );
362}
363
364/*
Simon Butchere4ed3472015-12-22 15:26:57 +0000365 * Count leading zero bits in a given integer
366 */
367static size_t int_clz( const t_uint x )
368{
369 size_t j;
370 t_uint mask = (t_uint) 1 << (biL - 1);
371
372 for( j = 0; j < biL; j++ )
373 {
374 if( x & mask ) break;
375
376 mask >>= 1;
377 }
378
379 return j;
380}
381
382/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000383 * Return the number of most significant bits
384 */
Paul Bakker23986e52011-04-24 08:57:21 +0000385size_t mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000386{
Paul Bakker23986e52011-04-24 08:57:21 +0000387 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000388
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200389 if( X->n == 0 )
390 return( 0 );
391
Paul Bakker5121ce52009-01-03 21:22:43 +0000392 for( i = X->n - 1; i > 0; i-- )
393 if( X->p[i] != 0 )
394 break;
395
Simon Butchere4ed3472015-12-22 15:26:57 +0000396 j = biL - int_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000397
Paul Bakker23986e52011-04-24 08:57:21 +0000398 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000399}
400
401/*
402 * Return the total size in bytes
403 */
Paul Bakker23986e52011-04-24 08:57:21 +0000404size_t mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000405{
406 return( ( mpi_msb( X ) + 7 ) >> 3 );
407}
408
409/*
410 * Convert an ASCII character to digit value
411 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000412static int mpi_get_digit( t_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000413{
414 *d = 255;
415
416 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
417 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
418 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
419
Paul Bakkera755ca12011-04-24 09:11:17 +0000420 if( *d >= (t_uint) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000421 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000422
423 return( 0 );
424}
425
426/*
427 * Import from an ASCII string
428 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000429int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000430{
Paul Bakker23986e52011-04-24 08:57:21 +0000431 int ret;
432 size_t i, j, slen, n;
Paul Bakkera755ca12011-04-24 09:11:17 +0000433 t_uint d;
Paul Bakker5121ce52009-01-03 21:22:43 +0000434 mpi T;
435
436 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000437 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000438
Paul Bakker6c591fa2011-05-05 11:49:20 +0000439 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000440
Paul Bakkerff60ee62010-03-16 21:09:09 +0000441 slen = strlen( s );
442
Paul Bakker5121ce52009-01-03 21:22:43 +0000443 if( radix == 16 )
444 {
Manuel Pégourié-Gonnardfa647a72015-10-05 15:23:11 +0100445 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard59efb6a2015-09-28 13:48:04 +0200446 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
447
Paul Bakkerff60ee62010-03-16 21:09:09 +0000448 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000449
450 MPI_CHK( mpi_grow( X, n ) );
451 MPI_CHK( mpi_lset( X, 0 ) );
452
Paul Bakker23986e52011-04-24 08:57:21 +0000453 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000454 {
Paul Bakker23986e52011-04-24 08:57:21 +0000455 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000456 {
457 X->s = -1;
458 break;
459 }
460
Paul Bakker23986e52011-04-24 08:57:21 +0000461 MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200462 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000463 }
464 }
465 else
466 {
467 MPI_CHK( mpi_lset( X, 0 ) );
468
Paul Bakkerff60ee62010-03-16 21:09:09 +0000469 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000470 {
471 if( i == 0 && s[i] == '-' )
472 {
473 X->s = -1;
474 continue;
475 }
476
477 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
478 MPI_CHK( mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000479
480 if( X->s == 1 )
481 {
482 MPI_CHK( mpi_add_int( X, &T, d ) );
483 }
484 else
485 {
486 MPI_CHK( mpi_sub_int( X, &T, d ) );
487 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000488 }
489 }
490
491cleanup:
492
Paul Bakker6c591fa2011-05-05 11:49:20 +0000493 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494
495 return( ret );
496}
497
498/*
499 * Helper to write the digits high-order first
500 */
501static int mpi_write_hlp( mpi *X, int radix, char **p )
502{
503 int ret;
Paul Bakkera755ca12011-04-24 09:11:17 +0000504 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000505
506 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000507 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000508
509 MPI_CHK( mpi_mod_int( &r, X, radix ) );
510 MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
511
512 if( mpi_cmp_int( X, 0 ) != 0 )
513 MPI_CHK( mpi_write_hlp( X, radix, p ) );
514
515 if( r < 10 )
516 *(*p)++ = (char)( r + 0x30 );
517 else
518 *(*p)++ = (char)( r + 0x37 );
519
520cleanup:
521
522 return( ret );
523}
524
525/*
526 * Export into an ASCII string
527 */
Paul Bakker23986e52011-04-24 08:57:21 +0000528int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000529{
Paul Bakker23986e52011-04-24 08:57:21 +0000530 int ret = 0;
531 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000532 char *p;
533 mpi T;
534
535 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000536 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000537
538 n = mpi_msb( X );
539 if( radix >= 4 ) n >>= 1;
540 if( radix >= 16 ) n >>= 1;
541 n += 3;
542
543 if( *slen < n )
544 {
545 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000546 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000547 }
548
549 p = s;
Paul Bakker6c591fa2011-05-05 11:49:20 +0000550 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000551
552 if( X->s == -1 )
553 *p++ = '-';
554
555 if( radix == 16 )
556 {
Paul Bakker23986e52011-04-24 08:57:21 +0000557 int c;
558 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000559
Paul Bakker23986e52011-04-24 08:57:21 +0000560 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000561 {
Paul Bakker23986e52011-04-24 08:57:21 +0000562 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000563 {
Paul Bakker23986e52011-04-24 08:57:21 +0000564 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000565
Paul Bakker6c343d72014-07-10 14:36:19 +0200566 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000567 continue;
568
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000569 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000570 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000571 k = 1;
572 }
573 }
574 }
575 else
576 {
577 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000578
579 if( T.s == -1 )
580 T.s = 1;
581
Paul Bakker5121ce52009-01-03 21:22:43 +0000582 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
583 }
584
585 *p++ = '\0';
586 *slen = p - s;
587
588cleanup:
589
Paul Bakker6c591fa2011-05-05 11:49:20 +0000590 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000591
592 return( ret );
593}
594
Paul Bakker335db3f2011-04-25 15:28:35 +0000595#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000596/*
597 * Read X from an opened file
598 */
599int mpi_read_file( mpi *X, int radix, FILE *fin )
600{
Paul Bakkera755ca12011-04-24 09:11:17 +0000601 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000602 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000603 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000604 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000605 * Buffer should have space for (short) label and decimal formatted MPI,
606 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000607 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000608 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000609
610 memset( s, 0, sizeof( s ) );
611 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000612 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000613
614 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000615 if( slen == sizeof( s ) - 2 )
616 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
617
Paul Bakker5121ce52009-01-03 21:22:43 +0000618 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
619 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
620
621 p = s + slen;
622 while( --p >= s )
623 if( mpi_get_digit( &d, radix, *p ) != 0 )
624 break;
625
626 return( mpi_read_string( X, radix, p + 1 ) );
627}
628
629/*
630 * Write X into an opened file (or stdout if fout == NULL)
631 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000632int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000633{
Paul Bakker23986e52011-04-24 08:57:21 +0000634 int ret;
635 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000636 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000637 * Buffer should have space for (short) label and decimal formatted MPI,
638 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000639 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000640 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000641
642 n = sizeof( s );
643 memset( s, 0, n );
644 n -= 2;
645
Paul Bakker23986e52011-04-24 08:57:21 +0000646 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000647
648 if( p == NULL ) p = "";
649
650 plen = strlen( p );
651 slen = strlen( s );
652 s[slen++] = '\r';
653 s[slen++] = '\n';
654
655 if( fout != NULL )
656 {
657 if( fwrite( p, 1, plen, fout ) != plen ||
658 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000659 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000660 }
661 else
Paul Bakker7dc4c442014-02-01 22:50:26 +0100662 polarssl_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000663
664cleanup:
665
666 return( ret );
667}
Paul Bakker335db3f2011-04-25 15:28:35 +0000668#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000669
670/*
671 * Import X from unsigned binary data, big endian
672 */
Paul Bakker23986e52011-04-24 08:57:21 +0000673int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000674{
Paul Bakker23986e52011-04-24 08:57:21 +0000675 int ret;
676 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000677
678 for( n = 0; n < buflen; n++ )
679 if( buf[n] != 0 )
680 break;
681
682 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
683 MPI_CHK( mpi_lset( X, 0 ) );
684
Paul Bakker23986e52011-04-24 08:57:21 +0000685 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000686 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000687
688cleanup:
689
690 return( ret );
691}
692
693/*
694 * Export X into unsigned binary data, big endian
695 */
Paul Bakker23986e52011-04-24 08:57:21 +0000696int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000697{
Paul Bakker23986e52011-04-24 08:57:21 +0000698 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000699
700 n = mpi_size( X );
701
702 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000703 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000704
705 memset( buf, 0, buflen );
706
707 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
708 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
709
710 return( 0 );
711}
712
713/*
714 * Left-shift: X <<= count
715 */
Paul Bakker23986e52011-04-24 08:57:21 +0000716int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000717{
Paul Bakker23986e52011-04-24 08:57:21 +0000718 int ret;
719 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000720 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000721
722 v0 = count / (biL );
723 t1 = count & (biL - 1);
724
725 i = mpi_msb( X ) + count;
726
Paul Bakkerf9688572011-05-05 10:00:45 +0000727 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000728 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
729
730 ret = 0;
731
732 /*
733 * shift by count / limb_size
734 */
735 if( v0 > 0 )
736 {
Paul Bakker23986e52011-04-24 08:57:21 +0000737 for( i = X->n; i > v0; i-- )
738 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000739
Paul Bakker23986e52011-04-24 08:57:21 +0000740 for( ; i > 0; i-- )
741 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000742 }
743
744 /*
745 * shift by count % limb_size
746 */
747 if( t1 > 0 )
748 {
749 for( i = v0; i < X->n; i++ )
750 {
751 r1 = X->p[i] >> (biL - t1);
752 X->p[i] <<= t1;
753 X->p[i] |= r0;
754 r0 = r1;
755 }
756 }
757
758cleanup:
759
760 return( ret );
761}
762
763/*
764 * Right-shift: X >>= count
765 */
Paul Bakker23986e52011-04-24 08:57:21 +0000766int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000767{
Paul Bakker23986e52011-04-24 08:57:21 +0000768 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000769 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000770
771 v0 = count / biL;
772 v1 = count & (biL - 1);
773
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100774 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
775 return mpi_lset( X, 0 );
776
Paul Bakker5121ce52009-01-03 21:22:43 +0000777 /*
778 * shift by count / limb_size
779 */
780 if( v0 > 0 )
781 {
782 for( i = 0; i < X->n - v0; i++ )
783 X->p[i] = X->p[i + v0];
784
785 for( ; i < X->n; i++ )
786 X->p[i] = 0;
787 }
788
789 /*
790 * shift by count % limb_size
791 */
792 if( v1 > 0 )
793 {
Paul Bakker23986e52011-04-24 08:57:21 +0000794 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000795 {
Paul Bakker23986e52011-04-24 08:57:21 +0000796 r1 = X->p[i - 1] << (biL - v1);
797 X->p[i - 1] >>= v1;
798 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000799 r0 = r1;
800 }
801 }
802
803 return( 0 );
804}
805
806/*
807 * Compare unsigned values
808 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000809int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000810{
Paul Bakker23986e52011-04-24 08:57:21 +0000811 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000812
Paul Bakker23986e52011-04-24 08:57:21 +0000813 for( i = X->n; i > 0; i-- )
814 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000815 break;
816
Paul Bakker23986e52011-04-24 08:57:21 +0000817 for( j = Y->n; j > 0; j-- )
818 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000819 break;
820
Paul Bakker23986e52011-04-24 08:57:21 +0000821 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000822 return( 0 );
823
824 if( i > j ) return( 1 );
825 if( j > i ) return( -1 );
826
Paul Bakker23986e52011-04-24 08:57:21 +0000827 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000828 {
Paul Bakker23986e52011-04-24 08:57:21 +0000829 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
830 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000831 }
832
833 return( 0 );
834}
835
836/*
837 * Compare signed values
838 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000839int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000840{
Paul Bakker23986e52011-04-24 08:57:21 +0000841 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000842
Paul Bakker23986e52011-04-24 08:57:21 +0000843 for( i = X->n; i > 0; i-- )
844 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000845 break;
846
Paul Bakker23986e52011-04-24 08:57:21 +0000847 for( j = Y->n; j > 0; j-- )
848 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000849 break;
850
Paul Bakker23986e52011-04-24 08:57:21 +0000851 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000852 return( 0 );
853
854 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000855 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000856
857 if( X->s > 0 && Y->s < 0 ) return( 1 );
858 if( Y->s > 0 && X->s < 0 ) return( -1 );
859
Paul Bakker23986e52011-04-24 08:57:21 +0000860 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000861 {
Paul Bakker23986e52011-04-24 08:57:21 +0000862 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
863 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000864 }
865
866 return( 0 );
867}
868
869/*
870 * Compare signed values
871 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000872int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000873{
874 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000875 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000876
877 *p = ( z < 0 ) ? -z : z;
878 Y.s = ( z < 0 ) ? -1 : 1;
879 Y.n = 1;
880 Y.p = p;
881
882 return( mpi_cmp_mpi( X, &Y ) );
883}
884
885/*
886 * Unsigned addition: X = |A| + |B| (HAC 14.7)
887 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000888int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000889{
Paul Bakker23986e52011-04-24 08:57:21 +0000890 int ret;
891 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000892 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000893
894 if( X == B )
895 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000896 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000897 }
898
899 if( X != A )
900 MPI_CHK( mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200901
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000902 /*
903 * X should always be positive as a result of unsigned additions.
904 */
905 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000906
Paul Bakker23986e52011-04-24 08:57:21 +0000907 for( j = B->n; j > 0; j-- )
908 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000909 break;
910
Paul Bakker23986e52011-04-24 08:57:21 +0000911 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000912
913 o = B->p; p = X->p; c = 0;
914
Paul Bakker23986e52011-04-24 08:57:21 +0000915 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000916 {
917 *p += c; c = ( *p < c );
918 *p += *o; c += ( *p < *o );
919 }
920
921 while( c != 0 )
922 {
923 if( i >= X->n )
924 {
925 MPI_CHK( mpi_grow( X, i + 1 ) );
926 p = X->p + i;
927 }
928
Paul Bakker2d319fd2012-09-16 21:34:26 +0000929 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000930 }
931
932cleanup:
933
934 return( ret );
935}
936
937/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100938 * Helper for mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000939 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000940static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000941{
Paul Bakker23986e52011-04-24 08:57:21 +0000942 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000943 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000944
945 for( i = c = 0; i < n; i++, s++, d++ )
946 {
947 z = ( *d < c ); *d -= c;
948 c = ( *d < *s ) + z; *d -= *s;
949 }
950
951 while( c != 0 )
952 {
953 z = ( *d < c ); *d -= c;
954 c = z; i++; d++;
955 }
956}
957
958/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100959 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000960 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000961int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000962{
963 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000964 int ret;
965 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000966
967 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000968 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000969
Paul Bakker6c591fa2011-05-05 11:49:20 +0000970 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000971
972 if( X == B )
973 {
974 MPI_CHK( mpi_copy( &TB, B ) );
975 B = &TB;
976 }
977
978 if( X != A )
979 MPI_CHK( mpi_copy( X, A ) );
980
Paul Bakker1ef7a532009-06-20 10:50:55 +0000981 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100982 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000983 */
984 X->s = 1;
985
Paul Bakker5121ce52009-01-03 21:22:43 +0000986 ret = 0;
987
Paul Bakker23986e52011-04-24 08:57:21 +0000988 for( n = B->n; n > 0; n-- )
989 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000990 break;
991
Paul Bakker23986e52011-04-24 08:57:21 +0000992 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000993
994cleanup:
995
Paul Bakker6c591fa2011-05-05 11:49:20 +0000996 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000997
998 return( ret );
999}
1000
1001/*
1002 * Signed addition: X = A + B
1003 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001004int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001005{
1006 int ret, s = A->s;
1007
1008 if( A->s * B->s < 0 )
1009 {
1010 if( mpi_cmp_abs( A, B ) >= 0 )
1011 {
1012 MPI_CHK( mpi_sub_abs( X, A, B ) );
1013 X->s = s;
1014 }
1015 else
1016 {
1017 MPI_CHK( mpi_sub_abs( X, B, A ) );
1018 X->s = -s;
1019 }
1020 }
1021 else
1022 {
1023 MPI_CHK( mpi_add_abs( X, A, B ) );
1024 X->s = s;
1025 }
1026
1027cleanup:
1028
1029 return( ret );
1030}
1031
1032/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001033 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001034 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001035int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001036{
1037 int ret, s = A->s;
1038
1039 if( A->s * B->s > 0 )
1040 {
1041 if( mpi_cmp_abs( A, B ) >= 0 )
1042 {
1043 MPI_CHK( mpi_sub_abs( X, A, B ) );
1044 X->s = s;
1045 }
1046 else
1047 {
1048 MPI_CHK( mpi_sub_abs( X, B, A ) );
1049 X->s = -s;
1050 }
1051 }
1052 else
1053 {
1054 MPI_CHK( mpi_add_abs( X, A, B ) );
1055 X->s = s;
1056 }
1057
1058cleanup:
1059
1060 return( ret );
1061}
1062
1063/*
1064 * Signed addition: X = A + b
1065 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001066int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001067{
1068 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001069 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001070
1071 p[0] = ( b < 0 ) ? -b : b;
1072 _B.s = ( b < 0 ) ? -1 : 1;
1073 _B.n = 1;
1074 _B.p = p;
1075
1076 return( mpi_add_mpi( X, A, &_B ) );
1077}
1078
1079/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001080 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001081 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001082int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001083{
1084 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001085 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001086
1087 p[0] = ( b < 0 ) ? -b : b;
1088 _B.s = ( b < 0 ) ? -1 : 1;
1089 _B.n = 1;
1090 _B.p = p;
1091
1092 return( mpi_sub_mpi( X, A, &_B ) );
1093}
1094
1095/*
1096 * Helper for mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001097 */
1098static
1099#if defined(__APPLE__) && defined(__arm__)
1100/*
1101 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1102 * appears to need this to prevent bad ARM code generation at -O3.
1103 */
1104__attribute__ ((noinline))
1105#endif
1106void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001107{
Paul Bakkera755ca12011-04-24 09:11:17 +00001108 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001109
1110#if defined(MULADDC_HUIT)
1111 for( ; i >= 8; i -= 8 )
1112 {
1113 MULADDC_INIT
1114 MULADDC_HUIT
1115 MULADDC_STOP
1116 }
1117
1118 for( ; i > 0; i-- )
1119 {
1120 MULADDC_INIT
1121 MULADDC_CORE
1122 MULADDC_STOP
1123 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001124#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001125 for( ; i >= 16; i -= 16 )
1126 {
1127 MULADDC_INIT
1128 MULADDC_CORE MULADDC_CORE
1129 MULADDC_CORE MULADDC_CORE
1130 MULADDC_CORE MULADDC_CORE
1131 MULADDC_CORE MULADDC_CORE
1132
1133 MULADDC_CORE MULADDC_CORE
1134 MULADDC_CORE MULADDC_CORE
1135 MULADDC_CORE MULADDC_CORE
1136 MULADDC_CORE MULADDC_CORE
1137 MULADDC_STOP
1138 }
1139
1140 for( ; i >= 8; i -= 8 )
1141 {
1142 MULADDC_INIT
1143 MULADDC_CORE MULADDC_CORE
1144 MULADDC_CORE MULADDC_CORE
1145
1146 MULADDC_CORE MULADDC_CORE
1147 MULADDC_CORE MULADDC_CORE
1148 MULADDC_STOP
1149 }
1150
1151 for( ; i > 0; i-- )
1152 {
1153 MULADDC_INIT
1154 MULADDC_CORE
1155 MULADDC_STOP
1156 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001157#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001158
1159 t++;
1160
1161 do {
1162 *d += c; c = ( *d < c ); d++;
1163 }
1164 while( c != 0 );
1165}
1166
1167/*
1168 * Baseline multiplication: X = A * B (HAC 14.12)
1169 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001170int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001171{
Paul Bakker23986e52011-04-24 08:57:21 +00001172 int ret;
1173 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001174 mpi TA, TB;
1175
Paul Bakker6c591fa2011-05-05 11:49:20 +00001176 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001177
1178 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1179 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1180
Paul Bakker23986e52011-04-24 08:57:21 +00001181 for( i = A->n; i > 0; i-- )
1182 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001183 break;
1184
Paul Bakker23986e52011-04-24 08:57:21 +00001185 for( j = B->n; j > 0; j-- )
1186 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001187 break;
1188
Paul Bakker23986e52011-04-24 08:57:21 +00001189 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001190 MPI_CHK( mpi_lset( X, 0 ) );
1191
Paul Bakker23986e52011-04-24 08:57:21 +00001192 for( i++; j > 0; j-- )
1193 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001194
1195 X->s = A->s * B->s;
1196
1197cleanup:
1198
Paul Bakker6c591fa2011-05-05 11:49:20 +00001199 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001200
1201 return( ret );
1202}
1203
1204/*
1205 * Baseline multiplication: X = A * b
1206 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001207int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001208{
1209 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001210 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001211
1212 _B.s = 1;
1213 _B.n = 1;
1214 _B.p = p;
1215 p[0] = b;
1216
1217 return( mpi_mul_mpi( X, A, &_B ) );
1218}
1219
1220/*
Simon Butcher14400c82016-01-02 00:08:13 +00001221 * Unsigned integer divide - double t_uint, dividend, u1/u0, and t_uint
1222 * divisor, d
Simon Butchere4ed3472015-12-22 15:26:57 +00001223 */
Simon Butcher14400c82016-01-02 00:08:13 +00001224static t_uint int_div_int( t_uint u1, t_uint u0, t_uint d, t_uint *r )
Simon Butchere4ed3472015-12-22 15:26:57 +00001225{
1226#if defined(POLARSSL_HAVE_UDBL)
1227 t_udbl dividend, quotient;
Simon Butcher14400c82016-01-02 00:08:13 +00001228#else
1229 const t_uint radix = 1 << biH;
1230 t_uint d0, d1, q0, q1, rAX, r0, quotient;
1231 t_uint u0_msw, u0_lsw;
1232 int s;
Simon Butchere4ed3472015-12-22 15:26:57 +00001233#endif
1234
1235 /*
1236 * Check for overflow
1237 */
Simon Butcher14400c82016-01-02 00:08:13 +00001238 if( 0 == d || u1 >= d )
Simon Butchere4ed3472015-12-22 15:26:57 +00001239 {
Simon Butcher14400c82016-01-02 00:08:13 +00001240 if ( r != NULL ) *r = ~0;
Simon Butchere4ed3472015-12-22 15:26:57 +00001241
Simon Butcher14400c82016-01-02 00:08:13 +00001242 return ( ~0 );
Simon Butchere4ed3472015-12-22 15:26:57 +00001243 }
1244
1245#if defined(POLARSSL_HAVE_UDBL)
1246 dividend = (t_udbl) u1 << biL;
1247 dividend |= (t_udbl) u0;
1248 quotient = dividend / d;
1249 if( quotient > ( (t_udbl) 1 << biL ) - 1 )
1250 quotient = ( (t_udbl) 1 << biL ) - 1;
1251
1252 if( r != NULL )
1253 *r = dividend - (quotient * d);
1254
1255 return (t_uint) quotient;
1256#else
Simon Butchere4ed3472015-12-22 15:26:57 +00001257
1258 /*
1259 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1260 * Vol. 2 - Seminumerical Algorithms, Knuth
1261 */
1262
1263 /*
1264 * Normalize the divisor, d, and dividend, u0, u1
1265 */
1266 s = int_clz( d );
1267 d = d << s;
1268
1269 u1 = u1 << s;
Simon Butcher14400c82016-01-02 00:08:13 +00001270 u1 |= ( u0 >> ( 32 - s ) ) & ( -s >> 31 );
Simon Butchere4ed3472015-12-22 15:26:57 +00001271 u0 = u0 << s;
1272
1273 d1 = d >> biH;
1274 d0 = d & 0xffff;
1275
1276 u0_msw = u0 >> biH;
1277 u0_lsw = u0 & 0xffff;
1278
1279 /*
1280 * Find the first quotient and remainder
1281 */
1282 q1 = u1 / d1;
1283 r0 = u1 - d1 * q1;
1284
1285 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1286 {
1287 q1 -= 1;
1288 r0 += d1;
1289
1290 if ( r0 >= radix ) break;
1291 }
1292
Simon Butcher14400c82016-01-02 00:08:13 +00001293 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butchere4ed3472015-12-22 15:26:57 +00001294 q0 = rAX / d1;
1295 r0 = rAX - q0 * d1;
1296
1297 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1298 {
1299 q0 -= 1;
1300 r0 += d1;
1301
1302 if ( r0 >= radix ) break;
1303 }
1304
1305 if (r != NULL)
Simon Butcher14400c82016-01-02 00:08:13 +00001306 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butchere4ed3472015-12-22 15:26:57 +00001307
1308 quotient = q1 * radix + q0;
1309
1310 return quotient;
1311#endif
1312}
1313
1314/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001315 * Division by mpi: A = Q * B + R (HAC 14.20)
1316 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001317int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001318{
Paul Bakker23986e52011-04-24 08:57:21 +00001319 int ret;
1320 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001321 mpi X, Y, Z, T1, T2;
1322
1323 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001324 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001325
Paul Bakker6c591fa2011-05-05 11:49:20 +00001326 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1327 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001328
1329 if( mpi_cmp_abs( A, B ) < 0 )
1330 {
1331 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1332 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1333 return( 0 );
1334 }
1335
1336 MPI_CHK( mpi_copy( &X, A ) );
1337 MPI_CHK( mpi_copy( &Y, B ) );
1338 X.s = Y.s = 1;
1339
1340 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1341 MPI_CHK( mpi_lset( &Z, 0 ) );
1342 MPI_CHK( mpi_grow( &T1, 2 ) );
1343 MPI_CHK( mpi_grow( &T2, 3 ) );
1344
1345 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001346 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001347 {
1348 k = biL - 1 - k;
1349 MPI_CHK( mpi_shift_l( &X, k ) );
1350 MPI_CHK( mpi_shift_l( &Y, k ) );
1351 }
1352 else k = 0;
1353
1354 n = X.n - 1;
1355 t = Y.n - 1;
Paul Bakker66d5d072014-06-17 16:39:18 +02001356 MPI_CHK( mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001357
1358 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1359 {
1360 Z.p[n - t]++;
Paul Bakker6ea1a952013-12-31 11:16:03 +01001361 MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001362 }
Paul Bakker66d5d072014-06-17 16:39:18 +02001363 MPI_CHK( mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001364
1365 for( i = n; i > t ; i-- )
1366 {
1367 if( X.p[i] >= Y.p[t] )
1368 Z.p[i - t - 1] = ~0;
1369 else
1370 {
Simon Butchere4ed3472015-12-22 15:26:57 +00001371 Z.p[i - t - 1] = int_div_int( X.p[i], X.p[i - 1], Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001372 }
1373
1374 Z.p[i - t - 1]++;
1375 do
1376 {
1377 Z.p[i - t - 1]--;
1378
1379 MPI_CHK( mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001380 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001381 T1.p[1] = Y.p[t];
1382 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1383
1384 MPI_CHK( mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001385 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1386 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001387 T2.p[2] = X.p[i];
1388 }
1389 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1390
1391 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001392 MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001393 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1394
1395 if( mpi_cmp_int( &X, 0 ) < 0 )
1396 {
1397 MPI_CHK( mpi_copy( &T1, &Y ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001398 MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001399 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1400 Z.p[i - t - 1]--;
1401 }
1402 }
1403
1404 if( Q != NULL )
1405 {
Paul Bakker6ea1a952013-12-31 11:16:03 +01001406 MPI_CHK( mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001407 Q->s = A->s * B->s;
1408 }
1409
1410 if( R != NULL )
1411 {
Paul Bakker6ea1a952013-12-31 11:16:03 +01001412 MPI_CHK( mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001413 X.s = A->s;
Paul Bakker6ea1a952013-12-31 11:16:03 +01001414 MPI_CHK( mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001415
Paul Bakker5121ce52009-01-03 21:22:43 +00001416 if( mpi_cmp_int( R, 0 ) == 0 )
1417 R->s = 1;
1418 }
1419
1420cleanup:
1421
Paul Bakker6c591fa2011-05-05 11:49:20 +00001422 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1423 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001424
1425 return( ret );
1426}
1427
1428/*
1429 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001430 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001431int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001432{
1433 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001434 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001435
1436 p[0] = ( b < 0 ) ? -b : b;
1437 _B.s = ( b < 0 ) ? -1 : 1;
1438 _B.n = 1;
1439 _B.p = p;
1440
1441 return( mpi_div_mpi( Q, R, A, &_B ) );
1442}
1443
1444/*
1445 * Modulo: R = A mod B
1446 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001447int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001448{
1449 int ret;
1450
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001451 if( mpi_cmp_int( B, 0 ) < 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001452 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001453
Paul Bakker5121ce52009-01-03 21:22:43 +00001454 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1455
1456 while( mpi_cmp_int( R, 0 ) < 0 )
1457 MPI_CHK( mpi_add_mpi( R, R, B ) );
1458
1459 while( mpi_cmp_mpi( R, B ) >= 0 )
1460 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1461
1462cleanup:
1463
1464 return( ret );
1465}
1466
1467/*
1468 * Modulo: r = A mod b
1469 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001470int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001471{
Paul Bakker23986e52011-04-24 08:57:21 +00001472 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001473 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001474
1475 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001476 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001477
1478 if( b < 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001479 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001480
1481 /*
1482 * handle trivial cases
1483 */
1484 if( b == 1 )
1485 {
1486 *r = 0;
1487 return( 0 );
1488 }
1489
1490 if( b == 2 )
1491 {
1492 *r = A->p[0] & 1;
1493 return( 0 );
1494 }
1495
1496 /*
1497 * general case
1498 */
Paul Bakker23986e52011-04-24 08:57:21 +00001499 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001500 {
Paul Bakker23986e52011-04-24 08:57:21 +00001501 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001502 y = ( y << biH ) | ( x >> biH );
1503 z = y / b;
1504 y -= z * b;
1505
1506 x <<= biH;
1507 y = ( y << biH ) | ( x >> biH );
1508 z = y / b;
1509 y -= z * b;
1510 }
1511
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001512 /*
1513 * If A is negative, then the current y represents a negative value.
1514 * Flipping it to the positive side.
1515 */
1516 if( A->s < 0 && y != 0 )
1517 y = b - y;
1518
Paul Bakker5121ce52009-01-03 21:22:43 +00001519 *r = y;
1520
1521 return( 0 );
1522}
1523
1524/*
1525 * Fast Montgomery initialization (thanks to Tom St Denis)
1526 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001527static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001528{
Paul Bakkera755ca12011-04-24 09:11:17 +00001529 t_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001530 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001531
1532 x = m0;
1533 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001534
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001535 for( i = biL; i >= 8; i /= 2 )
1536 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001537
1538 *mm = ~x + 1;
1539}
1540
1541/*
1542 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1543 */
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02001544static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm,
1545 const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001546{
Paul Bakker23986e52011-04-24 08:57:21 +00001547 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001548 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001549
1550 memset( T->p, 0, T->n * ciL );
1551
1552 d = T->p;
1553 n = N->n;
1554 m = ( B->n < n ) ? B->n : n;
1555
1556 for( i = 0; i < n; i++ )
1557 {
1558 /*
1559 * T = (T + u0*B + u1*N) / 2^biL
1560 */
1561 u0 = A->p[i];
1562 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1563
1564 mpi_mul_hlp( m, B->p, d, u0 );
1565 mpi_mul_hlp( n, N->p, d, u1 );
1566
1567 *d++ = u0; d[n + 1] = 0;
1568 }
1569
Paul Bakker66d5d072014-06-17 16:39:18 +02001570 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001571
1572 if( mpi_cmp_abs( A, N ) >= 0 )
1573 mpi_sub_hlp( n, N->p, A->p );
1574 else
1575 /* prevent timing attacks */
1576 mpi_sub_hlp( n, A->p, T->p );
1577}
1578
1579/*
1580 * Montgomery reduction: A = A * R^-1 mod N
1581 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001582static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001583{
Paul Bakkera755ca12011-04-24 09:11:17 +00001584 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001585 mpi U;
1586
Paul Bakker8ddb6452013-02-27 14:56:33 +01001587 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001588 U.p = &z;
1589
1590 mpi_montmul( A, &U, N, mm, T );
1591}
1592
1593/*
1594 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1595 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001596int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001597{
Paul Bakker23986e52011-04-24 08:57:21 +00001598 int ret;
1599 size_t wbits, wsize, one = 1;
1600 size_t i, j, nblimbs;
1601 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001602 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001603 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1604 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001605
1606 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001607 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001608
Paul Bakkerf6198c12012-05-16 08:02:29 +00001609 if( mpi_cmp_int( E, 0 ) < 0 )
1610 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1611
1612 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001613 * Init temps and window size
1614 */
1615 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001616 mpi_init( &RR ); mpi_init( &T );
Manuel Pégourié-Gonnardfd6a1912014-01-18 19:05:23 +01001617 mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001618 memset( W, 0, sizeof( W ) );
1619
1620 i = mpi_msb( E );
1621
1622 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1623 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1624
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001625 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1626 wsize = POLARSSL_MPI_WINDOW_SIZE;
1627
Paul Bakker5121ce52009-01-03 21:22:43 +00001628 j = N->n + 1;
1629 MPI_CHK( mpi_grow( X, j ) );
1630 MPI_CHK( mpi_grow( &W[1], j ) );
1631 MPI_CHK( mpi_grow( &T, j * 2 ) );
1632
1633 /*
Paul Bakker50546922012-05-19 08:40:49 +00001634 * Compensate for negative A (and correct at the end)
1635 */
1636 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001637 if( neg )
1638 {
1639 MPI_CHK( mpi_copy( &Apos, A ) );
1640 Apos.s = 1;
1641 A = &Apos;
1642 }
1643
1644 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001645 * If 1st call, pre-compute R^2 mod N
1646 */
1647 if( _RR == NULL || _RR->p == NULL )
1648 {
1649 MPI_CHK( mpi_lset( &RR, 1 ) );
1650 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1651 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1652
1653 if( _RR != NULL )
1654 memcpy( _RR, &RR, sizeof( mpi ) );
1655 }
1656 else
1657 memcpy( &RR, _RR, sizeof( mpi ) );
1658
1659 /*
1660 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1661 */
1662 if( mpi_cmp_mpi( A, N ) >= 0 )
Paul Bakkerc2024f42014-01-23 20:38:35 +01001663 MPI_CHK( mpi_mod_mpi( &W[1], A, N ) );
1664 else
1665 MPI_CHK( mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001666
1667 mpi_montmul( &W[1], &RR, N, mm, &T );
1668
1669 /*
1670 * X = R^2 * R^-1 mod N = R mod N
1671 */
1672 MPI_CHK( mpi_copy( X, &RR ) );
1673 mpi_montred( X, N, mm, &T );
1674
1675 if( wsize > 1 )
1676 {
1677 /*
1678 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1679 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001680 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001681
1682 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1683 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1684
1685 for( i = 0; i < wsize - 1; i++ )
1686 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001687
Paul Bakker5121ce52009-01-03 21:22:43 +00001688 /*
1689 * W[i] = W[i - 1] * W[1]
1690 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001691 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001692 {
1693 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1694 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1695
1696 mpi_montmul( &W[i], &W[1], N, mm, &T );
1697 }
1698 }
1699
1700 nblimbs = E->n;
1701 bufsize = 0;
1702 nbits = 0;
1703 wbits = 0;
1704 state = 0;
1705
1706 while( 1 )
1707 {
1708 if( bufsize == 0 )
1709 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001710 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001711 break;
1712
Paul Bakker0d7702c2013-10-29 16:18:35 +01001713 nblimbs--;
1714
Paul Bakkera755ca12011-04-24 09:11:17 +00001715 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001716 }
1717
1718 bufsize--;
1719
1720 ei = (E->p[nblimbs] >> bufsize) & 1;
1721
1722 /*
1723 * skip leading 0s
1724 */
1725 if( ei == 0 && state == 0 )
1726 continue;
1727
1728 if( ei == 0 && state == 1 )
1729 {
1730 /*
1731 * out of window, square X
1732 */
1733 mpi_montmul( X, X, N, mm, &T );
1734 continue;
1735 }
1736
1737 /*
1738 * add ei to current window
1739 */
1740 state = 2;
1741
1742 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001743 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001744
1745 if( nbits == wsize )
1746 {
1747 /*
1748 * X = X^wsize R^-1 mod N
1749 */
1750 for( i = 0; i < wsize; i++ )
1751 mpi_montmul( X, X, N, mm, &T );
1752
1753 /*
1754 * X = X * W[wbits] R^-1 mod N
1755 */
1756 mpi_montmul( X, &W[wbits], N, mm, &T );
1757
1758 state--;
1759 nbits = 0;
1760 wbits = 0;
1761 }
1762 }
1763
1764 /*
1765 * process the remaining bits
1766 */
1767 for( i = 0; i < nbits; i++ )
1768 {
1769 mpi_montmul( X, X, N, mm, &T );
1770
1771 wbits <<= 1;
1772
Paul Bakker66d5d072014-06-17 16:39:18 +02001773 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001774 mpi_montmul( X, &W[1], N, mm, &T );
1775 }
1776
1777 /*
1778 * X = A^E * R * R^-1 mod N = A^E mod N
1779 */
1780 mpi_montred( X, N, mm, &T );
1781
Paul Bakkerf6198c12012-05-16 08:02:29 +00001782 if( neg )
1783 {
1784 X->s = -1;
Paul Bakkerc2024f42014-01-23 20:38:35 +01001785 MPI_CHK( mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001786 }
1787
Paul Bakker5121ce52009-01-03 21:22:43 +00001788cleanup:
1789
Paul Bakker66d5d072014-06-17 16:39:18 +02001790 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001791 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001792
Paul Bakkerf6198c12012-05-16 08:02:29 +00001793 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001794
Paul Bakker75a28602014-03-31 12:08:17 +02001795 if( _RR == NULL || _RR->p == NULL )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001796 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001797
1798 return( ret );
1799}
1800
Paul Bakker5121ce52009-01-03 21:22:43 +00001801/*
1802 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1803 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001804int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001805{
Paul Bakker23986e52011-04-24 08:57:21 +00001806 int ret;
1807 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001808 mpi TG, TA, TB;
1809
Paul Bakker6c591fa2011-05-05 11:49:20 +00001810 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001811
Paul Bakker5121ce52009-01-03 21:22:43 +00001812 MPI_CHK( mpi_copy( &TA, A ) );
1813 MPI_CHK( mpi_copy( &TB, B ) );
1814
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001815 lz = mpi_lsb( &TA );
1816 lzt = mpi_lsb( &TB );
1817
Paul Bakker66d5d072014-06-17 16:39:18 +02001818 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001819 lz = lzt;
1820
1821 MPI_CHK( mpi_shift_r( &TA, lz ) );
1822 MPI_CHK( mpi_shift_r( &TB, lz ) );
1823
Paul Bakker5121ce52009-01-03 21:22:43 +00001824 TA.s = TB.s = 1;
1825
1826 while( mpi_cmp_int( &TA, 0 ) != 0 )
1827 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001828 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1829 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001830
1831 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1832 {
1833 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1834 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1835 }
1836 else
1837 {
1838 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1839 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1840 }
1841 }
1842
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001843 MPI_CHK( mpi_shift_l( &TB, lz ) );
1844 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001845
1846cleanup:
1847
Paul Bakker6c591fa2011-05-05 11:49:20 +00001848 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001849
1850 return( ret );
1851}
1852
Paul Bakker33dc46b2014-04-30 16:11:39 +02001853/*
1854 * Fill X with size bytes of random.
1855 *
1856 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001857 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001858 * deterministic, eg for tests).
1859 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001860int mpi_fill_random( mpi *X, size_t size,
1861 int (*f_rng)(void *, unsigned char *, size_t),
1862 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001863{
Paul Bakker23986e52011-04-24 08:57:21 +00001864 int ret;
Paul Bakker33dc46b2014-04-30 16:11:39 +02001865 unsigned char buf[POLARSSL_MPI_MAX_SIZE];
1866
1867 if( size > POLARSSL_MPI_MAX_SIZE )
1868 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001869
Paul Bakker33dc46b2014-04-30 16:11:39 +02001870 MPI_CHK( f_rng( p_rng, buf, size ) );
1871 MPI_CHK( mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001872
1873cleanup:
1874 return( ret );
1875}
1876
Paul Bakker5121ce52009-01-03 21:22:43 +00001877/*
1878 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1879 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001880int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001881{
1882 int ret;
1883 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1884
1885 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001886 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001887
Paul Bakker6c591fa2011-05-05 11:49:20 +00001888 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1889 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1890 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001891
1892 MPI_CHK( mpi_gcd( &G, A, N ) );
1893
1894 if( mpi_cmp_int( &G, 1 ) != 0 )
1895 {
Paul Bakker40e46942009-01-03 21:51:57 +00001896 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001897 goto cleanup;
1898 }
1899
1900 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1901 MPI_CHK( mpi_copy( &TU, &TA ) );
1902 MPI_CHK( mpi_copy( &TB, N ) );
1903 MPI_CHK( mpi_copy( &TV, N ) );
1904
1905 MPI_CHK( mpi_lset( &U1, 1 ) );
1906 MPI_CHK( mpi_lset( &U2, 0 ) );
1907 MPI_CHK( mpi_lset( &V1, 0 ) );
1908 MPI_CHK( mpi_lset( &V2, 1 ) );
1909
1910 do
1911 {
1912 while( ( TU.p[0] & 1 ) == 0 )
1913 {
1914 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1915
1916 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1917 {
1918 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1919 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1920 }
1921
1922 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1923 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1924 }
1925
1926 while( ( TV.p[0] & 1 ) == 0 )
1927 {
1928 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1929
1930 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1931 {
1932 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1933 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1934 }
1935
1936 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1937 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1938 }
1939
1940 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1941 {
1942 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1943 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1944 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1945 }
1946 else
1947 {
1948 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1949 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1950 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1951 }
1952 }
1953 while( mpi_cmp_int( &TU, 0 ) != 0 );
1954
1955 while( mpi_cmp_int( &V1, 0 ) < 0 )
1956 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1957
1958 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1959 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1960
1961 MPI_CHK( mpi_copy( X, &V1 ) );
1962
1963cleanup:
1964
Paul Bakker6c591fa2011-05-05 11:49:20 +00001965 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1966 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1967 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001968
1969 return( ret );
1970}
1971
Paul Bakkerd9374b02012-11-02 11:02:58 +00001972#if defined(POLARSSL_GENPRIME)
1973
Paul Bakker5121ce52009-01-03 21:22:43 +00001974static const int small_prime[] =
1975{
1976 3, 5, 7, 11, 13, 17, 19, 23,
1977 29, 31, 37, 41, 43, 47, 53, 59,
1978 61, 67, 71, 73, 79, 83, 89, 97,
1979 101, 103, 107, 109, 113, 127, 131, 137,
1980 139, 149, 151, 157, 163, 167, 173, 179,
1981 181, 191, 193, 197, 199, 211, 223, 227,
1982 229, 233, 239, 241, 251, 257, 263, 269,
1983 271, 277, 281, 283, 293, 307, 311, 313,
1984 317, 331, 337, 347, 349, 353, 359, 367,
1985 373, 379, 383, 389, 397, 401, 409, 419,
1986 421, 431, 433, 439, 443, 449, 457, 461,
1987 463, 467, 479, 487, 491, 499, 503, 509,
1988 521, 523, 541, 547, 557, 563, 569, 571,
1989 577, 587, 593, 599, 601, 607, 613, 617,
1990 619, 631, 641, 643, 647, 653, 659, 661,
1991 673, 677, 683, 691, 701, 709, 719, 727,
1992 733, 739, 743, 751, 757, 761, 769, 773,
1993 787, 797, 809, 811, 821, 823, 827, 829,
1994 839, 853, 857, 859, 863, 877, 881, 883,
1995 887, 907, 911, 919, 929, 937, 941, 947,
1996 953, 967, 971, 977, 983, 991, 997, -103
1997};
1998
1999/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002000 * Small divisors test (X must be positive)
2001 *
2002 * Return values:
2003 * 0: no small factor (possible prime, more tests needed)
2004 * 1: certain prime
2005 * POLARSSL_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2006 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002007 */
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002008static int mpi_check_small_factors( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002009{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002010 int ret = 0;
2011 size_t i;
2012 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002013
Paul Bakker5121ce52009-01-03 21:22:43 +00002014 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002015 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002016
2017 for( i = 0; small_prime[i] > 0; i++ )
2018 {
Paul Bakker5121ce52009-01-03 21:22:43 +00002019 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002020 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002021
2022 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
2023
2024 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002025 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002026 }
2027
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002028cleanup:
2029 return( ret );
2030}
2031
2032/*
2033 * Miller-Rabin pseudo-primality test (HAC 4.24)
2034 */
2035static int mpi_miller_rabin( const mpi *X,
2036 int (*f_rng)(void *, unsigned char *, size_t),
2037 void *p_rng )
2038{
Pascal Junodb99183d2015-03-11 16:49:45 +01002039 int ret, count;
2040 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002041 mpi W, R, T, A, RR;
2042
2043 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
2044 mpi_init( &RR );
2045
Paul Bakker5121ce52009-01-03 21:22:43 +00002046 /*
2047 * W = |X| - 1
2048 * R = W >> lsb( W )
2049 */
Paul Bakker5121ce52009-01-03 21:22:43 +00002050 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00002051 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00002052 MPI_CHK( mpi_copy( &R, &W ) );
2053 MPI_CHK( mpi_shift_r( &R, s ) );
2054
2055 i = mpi_msb( X );
2056 /*
2057 * HAC, table 4.4
2058 */
2059 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2060 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2061 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2062
2063 for( i = 0; i < n; i++ )
2064 {
2065 /*
2066 * pick a random A, 1 < A < |X| - 1
2067 */
Paul Bakker5121ce52009-01-03 21:22:43 +00002068
Pascal Junodb99183d2015-03-11 16:49:45 +01002069 count = 0;
2070 do {
2071 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
2072
2073 j = mpi_msb( &A );
2074 k = mpi_msb( &W );
2075 if (j > k) {
2076 MPI_CHK( mpi_shift_r( &A, j - k ) );
2077 }
2078
2079 if (count++ > 30) {
2080 return POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
2081 }
2082
2083 } while ( (mpi_cmp_mpi( &A, &W ) >= 0) ||
2084 (mpi_cmp_int( &A, 1 ) <= 0) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002085
2086 /*
2087 * A = A^R mod |X|
2088 */
2089 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
2090
2091 if( mpi_cmp_mpi( &A, &W ) == 0 ||
2092 mpi_cmp_int( &A, 1 ) == 0 )
2093 continue;
2094
2095 j = 1;
2096 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
2097 {
2098 /*
2099 * A = A * A mod |X|
2100 */
2101 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
2102 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
2103
2104 if( mpi_cmp_int( &A, 1 ) == 0 )
2105 break;
2106
2107 j++;
2108 }
2109
2110 /*
2111 * not prime if A != |X| - 1 or A == 1
2112 */
2113 if( mpi_cmp_mpi( &A, &W ) != 0 ||
2114 mpi_cmp_int( &A, 1 ) == 0 )
2115 {
Paul Bakker40e46942009-01-03 21:51:57 +00002116 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002117 break;
2118 }
2119 }
2120
2121cleanup:
Paul Bakker6c591fa2011-05-05 11:49:20 +00002122 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
2123 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002124
2125 return( ret );
2126}
2127
2128/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002129 * Pseudo-primality test: small factors, then Miller-Rabin
2130 */
Paul Bakker45f457d2013-11-25 14:26:52 +01002131int mpi_is_prime( mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002132 int (*f_rng)(void *, unsigned char *, size_t),
2133 void *p_rng )
2134{
2135 int ret;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002136 mpi XX;
2137
2138 XX.s = 1;
2139 XX.n = X->n;
2140 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002141
2142 if( mpi_cmp_int( &XX, 0 ) == 0 ||
2143 mpi_cmp_int( &XX, 1 ) == 0 )
2144 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
2145
2146 if( mpi_cmp_int( &XX, 2 ) == 0 )
2147 return( 0 );
2148
2149 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2150 {
2151 if( ret == 1 )
2152 return( 0 );
2153
2154 return( ret );
2155 }
2156
2157 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2158}
2159
2160/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002161 * Prime number generation
2162 */
Paul Bakker23986e52011-04-24 08:57:21 +00002163int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002164 int (*f_rng)(void *, unsigned char *, size_t),
2165 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002166{
Paul Bakker23986e52011-04-24 08:57:21 +00002167 int ret;
2168 size_t k, n;
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002169 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002170 mpi Y;
2171
Paul Bakkerfe3256e2011-11-25 12:11:43 +00002172 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00002173 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002174
Paul Bakker6c591fa2011-05-05 11:49:20 +00002175 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002176
2177 n = BITS_TO_LIMBS( nbits );
2178
Paul Bakker901c6562012-04-20 13:25:38 +00002179 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002180
2181 k = mpi_msb( X );
Pascal Junodb99183d2015-03-11 16:49:45 +01002182 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002183
Pascal Junodb99183d2015-03-11 16:49:45 +01002184 mpi_set_bit( X, nbits-1, 1 );
2185
2186 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002187
2188 if( dh_flag == 0 )
2189 {
2190 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
2191 {
Paul Bakker40e46942009-01-03 21:51:57 +00002192 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002193 goto cleanup;
2194
2195 MPI_CHK( mpi_add_int( X, X, 2 ) );
2196 }
2197 }
2198 else
2199 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002200 /*
2201 * An necessary condition for Y and X = 2Y + 1 to be prime
2202 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2203 * Make sure it is satisfied, while keeping X = 3 mod 4
2204 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002205
2206 X->p[0] |= 2;
2207
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002208 MPI_CHK( mpi_mod_int( &r, X, 3 ) );
2209 if( r == 0 )
2210 MPI_CHK( mpi_add_int( X, X, 8 ) );
2211 else if( r == 1 )
2212 MPI_CHK( mpi_add_int( X, X, 4 ) );
2213
2214 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2215 MPI_CHK( mpi_copy( &Y, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002216 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2217
2218 while( 1 )
2219 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002220 /*
2221 * First, check small factors for X and Y
2222 * before doing Miller-Rabin on any of them
2223 */
2224 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2225 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2226 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2227 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002228 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002229 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002230 }
2231
Paul Bakker40e46942009-01-03 21:51:57 +00002232 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002233 goto cleanup;
2234
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002235 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002236 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002237 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2238 * so up Y by 6 and X by 12.
2239 */
2240 MPI_CHK( mpi_add_int( X, X, 12 ) );
2241 MPI_CHK( mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002242 }
2243 }
2244
2245cleanup:
2246
Paul Bakker6c591fa2011-05-05 11:49:20 +00002247 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002248
2249 return( ret );
2250}
2251
Manuel Pégourié-Gonnarddf0142b2013-08-22 18:29:07 +02002252#endif /* POLARSSL_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002253
Paul Bakker40e46942009-01-03 21:51:57 +00002254#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002255
Paul Bakker23986e52011-04-24 08:57:21 +00002256#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002257
2258static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2259{
2260 { 693, 609, 21 },
2261 { 1764, 868, 28 },
2262 { 768454923, 542167814, 1 }
2263};
2264
Paul Bakker5121ce52009-01-03 21:22:43 +00002265/*
2266 * Checkup routine
2267 */
2268int mpi_self_test( int verbose )
2269{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002270 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002271 mpi A, E, N, X, Y, U, V;
2272
Paul Bakker6c591fa2011-05-05 11:49:20 +00002273 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2274 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002275
2276 MPI_CHK( mpi_read_string( &A, 16,
2277 "EFE021C2645FD1DC586E69184AF4A31E" \
2278 "D5F53E93B5F123FA41680867BA110131" \
2279 "944FE7952E2517337780CB0DB80E61AA" \
2280 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2281
2282 MPI_CHK( mpi_read_string( &E, 16,
2283 "B2E7EFD37075B9F03FF989C7C5051C20" \
2284 "34D2A323810251127E7BF8625A4F49A5" \
2285 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2286 "5B5C25763222FEFCCFC38B832366C29E" ) );
2287
2288 MPI_CHK( mpi_read_string( &N, 16,
2289 "0066A198186C18C10B2F5ED9B522752A" \
2290 "9830B69916E535C8F047518A889A43A5" \
2291 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2292
2293 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2294
2295 MPI_CHK( mpi_read_string( &U, 16,
2296 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2297 "9E857EA95A03512E2BAE7391688D264A" \
2298 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2299 "8001B72E848A38CAE1C65F78E56ABDEF" \
2300 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2301 "ECF677152EF804370C1A305CAF3B5BF1" \
2302 "30879B56C61DE584A0F53A2447A51E" ) );
2303
2304 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002305 polarssl_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002306
2307 if( mpi_cmp_mpi( &X, &U ) != 0 )
2308 {
2309 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002310 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002311
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002312 ret = 1;
2313 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002314 }
2315
2316 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002317 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002318
2319 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2320
2321 MPI_CHK( mpi_read_string( &U, 16,
2322 "256567336059E52CAE22925474705F39A94" ) );
2323
2324 MPI_CHK( mpi_read_string( &V, 16,
2325 "6613F26162223DF488E9CD48CC132C7A" \
2326 "0AC93C701B001B092E4E5B9F73BCD27B" \
2327 "9EE50D0657C77F374E903CDFA4C642" ) );
2328
2329 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002330 polarssl_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002331
2332 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2333 mpi_cmp_mpi( &Y, &V ) != 0 )
2334 {
2335 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002336 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002337
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002338 ret = 1;
2339 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002340 }
2341
2342 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002343 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002344
2345 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2346
2347 MPI_CHK( mpi_read_string( &U, 16,
2348 "36E139AEA55215609D2816998ED020BB" \
2349 "BD96C37890F65171D948E9BC7CBAA4D9" \
2350 "325D24D6A3C12710F10A09FA08AB87" ) );
2351
2352 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002353 polarssl_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002354
2355 if( mpi_cmp_mpi( &X, &U ) != 0 )
2356 {
2357 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002358 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002359
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002360 ret = 1;
2361 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002362 }
2363
2364 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002365 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002366
2367 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2368
2369 MPI_CHK( mpi_read_string( &U, 16,
2370 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2371 "C3DBA76456363A10869622EAC2DD84EC" \
2372 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2373
2374 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002375 polarssl_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002376
2377 if( mpi_cmp_mpi( &X, &U ) != 0 )
2378 {
2379 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002380 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002381
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002382 ret = 1;
2383 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002384 }
2385
2386 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002387 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002388
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002389 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002390 polarssl_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002391
Paul Bakker66d5d072014-06-17 16:39:18 +02002392 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002393 {
2394 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002395 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002396
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002397 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002398
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002399 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2400 {
2401 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002402 polarssl_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002403
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002404 ret = 1;
2405 goto cleanup;
2406 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002407 }
2408
2409 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002410 polarssl_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002411
Paul Bakker5121ce52009-01-03 21:22:43 +00002412cleanup:
2413
2414 if( ret != 0 && verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002415 polarssl_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002416
Paul Bakker6c591fa2011-05-05 11:49:20 +00002417 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2418 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002419
2420 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002421 polarssl_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002422
2423 return( ret );
2424}
2425
Paul Bakker9af723c2014-05-01 13:03:14 +02002426#endif /* POLARSSL_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002427
Paul Bakker9af723c2014-05-01 13:03:14 +02002428#endif /* POLARSSL_BIGNUM_C */