blob: e46ce0b525796d609fdf1274b3a4efc2d9d85c49 [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;
Janos Follath2b806fa2015-10-25 14:24:10 +0100892 mpi_uint *o, *p, c;
893 mpi TB;
Paul Bakker5121ce52009-01-03 21:22:43 +0000894
895 if( X == B )
896 {
Janos Follath2b806fa2015-10-25 14:24:10 +0100897 B = A; A = X;
898
Janos Follathff5317e2015-10-25 12:29:13 +0100899 if( B == A )
900 {
901 // Making a temporary copy instead of shifting by one to deny
902 // the possibility of corresponding side-channel attacks.
Janos Follathff5317e2015-10-25 12:29:13 +0100903 mpi_init( &TB );
Janos Follath2b806fa2015-10-25 14:24:10 +0100904 MPI_CHK( mpi_copy( &TB, B ) );
Janos Follath87f14942015-10-25 10:58:03 +0100905
Janos Follath2b806fa2015-10-25 14:24:10 +0100906 B = &TB;
Janos Follathff5317e2015-10-25 12:29:13 +0100907 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000908 }
909
910 if( X != A )
911 MPI_CHK( mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200912
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000913 /*
914 * X should always be positive as a result of unsigned additions.
915 */
916 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000917
Paul Bakker23986e52011-04-24 08:57:21 +0000918 for( j = B->n; j > 0; j-- )
919 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000920 break;
921
Paul Bakker23986e52011-04-24 08:57:21 +0000922 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000923
924 o = B->p; p = X->p; c = 0;
925
Paul Bakker23986e52011-04-24 08:57:21 +0000926 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000927 {
928 *p += c; c = ( *p < c );
929 *p += *o; c += ( *p < *o );
930 }
931
932 while( c != 0 )
933 {
934 if( i >= X->n )
935 {
936 MPI_CHK( mpi_grow( X, i + 1 ) );
937 p = X->p + i;
938 }
939
Paul Bakker2d319fd2012-09-16 21:34:26 +0000940 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000941 }
942
943cleanup:
Janos Follath2b806fa2015-10-25 14:24:10 +0100944 if( &TB == B )
945 {
946 mpi_free( &TB );
947 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000948
949 return( ret );
950}
951
952/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100953 * Helper for mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000954 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000955static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000956{
Paul Bakker23986e52011-04-24 08:57:21 +0000957 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000958 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000959
960 for( i = c = 0; i < n; i++, s++, d++ )
961 {
962 z = ( *d < c ); *d -= c;
963 c = ( *d < *s ) + z; *d -= *s;
964 }
965
966 while( c != 0 )
967 {
968 z = ( *d < c ); *d -= c;
969 c = z; i++; d++;
970 }
971}
972
973/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100974 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000975 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000976int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000977{
978 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000979 int ret;
980 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000981
982 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000983 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000984
Paul Bakker6c591fa2011-05-05 11:49:20 +0000985 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000986
987 if( X == B )
988 {
989 MPI_CHK( mpi_copy( &TB, B ) );
990 B = &TB;
991 }
992
993 if( X != A )
994 MPI_CHK( mpi_copy( X, A ) );
995
Paul Bakker1ef7a532009-06-20 10:50:55 +0000996 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100997 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000998 */
999 X->s = 1;
1000
Paul Bakker5121ce52009-01-03 21:22:43 +00001001 ret = 0;
1002
Paul Bakker23986e52011-04-24 08:57:21 +00001003 for( n = B->n; n > 0; n-- )
1004 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001005 break;
1006
Paul Bakker23986e52011-04-24 08:57:21 +00001007 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001008
1009cleanup:
1010
Paul Bakker6c591fa2011-05-05 11:49:20 +00001011 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001012
1013 return( ret );
1014}
1015
1016/*
1017 * Signed addition: X = A + B
1018 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001019int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001020{
1021 int ret, s = A->s;
1022
1023 if( A->s * B->s < 0 )
1024 {
1025 if( mpi_cmp_abs( A, B ) >= 0 )
1026 {
1027 MPI_CHK( mpi_sub_abs( X, A, B ) );
1028 X->s = s;
1029 }
1030 else
1031 {
1032 MPI_CHK( mpi_sub_abs( X, B, A ) );
1033 X->s = -s;
1034 }
1035 }
1036 else
1037 {
1038 MPI_CHK( mpi_add_abs( X, A, B ) );
1039 X->s = s;
1040 }
1041
1042cleanup:
1043
1044 return( ret );
1045}
1046
1047/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001048 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001049 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001050int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001051{
1052 int ret, s = A->s;
1053
1054 if( A->s * B->s > 0 )
1055 {
1056 if( mpi_cmp_abs( A, B ) >= 0 )
1057 {
1058 MPI_CHK( mpi_sub_abs( X, A, B ) );
1059 X->s = s;
1060 }
1061 else
1062 {
1063 MPI_CHK( mpi_sub_abs( X, B, A ) );
1064 X->s = -s;
1065 }
1066 }
1067 else
1068 {
1069 MPI_CHK( mpi_add_abs( X, A, B ) );
1070 X->s = s;
1071 }
1072
1073cleanup:
1074
1075 return( ret );
1076}
1077
1078/*
1079 * Signed addition: X = A + b
1080 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001081int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001082{
1083 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001084 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001085
1086 p[0] = ( b < 0 ) ? -b : b;
1087 _B.s = ( b < 0 ) ? -1 : 1;
1088 _B.n = 1;
1089 _B.p = p;
1090
1091 return( mpi_add_mpi( X, A, &_B ) );
1092}
1093
1094/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001095 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001096 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001097int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001098{
1099 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001100 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001101
1102 p[0] = ( b < 0 ) ? -b : b;
1103 _B.s = ( b < 0 ) ? -1 : 1;
1104 _B.n = 1;
1105 _B.p = p;
1106
1107 return( mpi_sub_mpi( X, A, &_B ) );
1108}
1109
1110/*
1111 * Helper for mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001112 */
1113static
1114#if defined(__APPLE__) && defined(__arm__)
1115/*
1116 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1117 * appears to need this to prevent bad ARM code generation at -O3.
1118 */
1119__attribute__ ((noinline))
1120#endif
1121void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001122{
Paul Bakkera755ca12011-04-24 09:11:17 +00001123 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001124
1125#if defined(MULADDC_HUIT)
1126 for( ; i >= 8; i -= 8 )
1127 {
1128 MULADDC_INIT
1129 MULADDC_HUIT
1130 MULADDC_STOP
1131 }
1132
1133 for( ; i > 0; i-- )
1134 {
1135 MULADDC_INIT
1136 MULADDC_CORE
1137 MULADDC_STOP
1138 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001139#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001140 for( ; i >= 16; i -= 16 )
1141 {
1142 MULADDC_INIT
1143 MULADDC_CORE MULADDC_CORE
1144 MULADDC_CORE MULADDC_CORE
1145 MULADDC_CORE MULADDC_CORE
1146 MULADDC_CORE MULADDC_CORE
1147
1148 MULADDC_CORE MULADDC_CORE
1149 MULADDC_CORE MULADDC_CORE
1150 MULADDC_CORE MULADDC_CORE
1151 MULADDC_CORE MULADDC_CORE
1152 MULADDC_STOP
1153 }
1154
1155 for( ; i >= 8; i -= 8 )
1156 {
1157 MULADDC_INIT
1158 MULADDC_CORE MULADDC_CORE
1159 MULADDC_CORE MULADDC_CORE
1160
1161 MULADDC_CORE MULADDC_CORE
1162 MULADDC_CORE MULADDC_CORE
1163 MULADDC_STOP
1164 }
1165
1166 for( ; i > 0; i-- )
1167 {
1168 MULADDC_INIT
1169 MULADDC_CORE
1170 MULADDC_STOP
1171 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001172#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001173
1174 t++;
1175
1176 do {
1177 *d += c; c = ( *d < c ); d++;
1178 }
1179 while( c != 0 );
1180}
1181
1182/*
1183 * Baseline multiplication: X = A * B (HAC 14.12)
1184 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001185int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001186{
Paul Bakker23986e52011-04-24 08:57:21 +00001187 int ret;
1188 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001189 mpi TA, TB;
1190
Paul Bakker6c591fa2011-05-05 11:49:20 +00001191 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001192
1193 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1194 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1195
Paul Bakker23986e52011-04-24 08:57:21 +00001196 for( i = A->n; i > 0; i-- )
1197 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001198 break;
1199
Paul Bakker23986e52011-04-24 08:57:21 +00001200 for( j = B->n; j > 0; j-- )
1201 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001202 break;
1203
Paul Bakker23986e52011-04-24 08:57:21 +00001204 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001205 MPI_CHK( mpi_lset( X, 0 ) );
1206
Paul Bakker23986e52011-04-24 08:57:21 +00001207 for( i++; j > 0; j-- )
1208 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001209
1210 X->s = A->s * B->s;
1211
1212cleanup:
1213
Paul Bakker6c591fa2011-05-05 11:49:20 +00001214 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001215
1216 return( ret );
1217}
1218
1219/*
1220 * Baseline multiplication: X = A * b
1221 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001222int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001223{
1224 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001225 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001226
1227 _B.s = 1;
1228 _B.n = 1;
1229 _B.p = p;
1230 p[0] = b;
1231
1232 return( mpi_mul_mpi( X, A, &_B ) );
1233}
1234
1235/*
Simon Butcher14400c82016-01-02 00:08:13 +00001236 * Unsigned integer divide - double t_uint, dividend, u1/u0, and t_uint
1237 * divisor, d
Simon Butchere4ed3472015-12-22 15:26:57 +00001238 */
Simon Butcher14400c82016-01-02 00:08:13 +00001239static t_uint int_div_int( t_uint u1, t_uint u0, t_uint d, t_uint *r )
Simon Butchere4ed3472015-12-22 15:26:57 +00001240{
1241#if defined(POLARSSL_HAVE_UDBL)
1242 t_udbl dividend, quotient;
Simon Butcher14400c82016-01-02 00:08:13 +00001243#else
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001244 const t_uint radix = (t_uint) 1 << biH;
1245 const t_uint uint_halfword_mask = ( (t_uint) 1 << biH ) - 1;
Simon Butcher14400c82016-01-02 00:08:13 +00001246 t_uint d0, d1, q0, q1, rAX, r0, quotient;
1247 t_uint u0_msw, u0_lsw;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001248 size_t s;
Simon Butchere4ed3472015-12-22 15:26:57 +00001249#endif
1250
1251 /*
1252 * Check for overflow
1253 */
Simon Butcher14400c82016-01-02 00:08:13 +00001254 if( 0 == d || u1 >= d )
Simon Butchere4ed3472015-12-22 15:26:57 +00001255 {
Simon Butcher14400c82016-01-02 00:08:13 +00001256 if ( r != NULL ) *r = ~0;
Simon Butchere4ed3472015-12-22 15:26:57 +00001257
Simon Butcher14400c82016-01-02 00:08:13 +00001258 return ( ~0 );
Simon Butchere4ed3472015-12-22 15:26:57 +00001259 }
1260
1261#if defined(POLARSSL_HAVE_UDBL)
1262 dividend = (t_udbl) u1 << biL;
1263 dividend |= (t_udbl) u0;
1264 quotient = dividend / d;
1265 if( quotient > ( (t_udbl) 1 << biL ) - 1 )
1266 quotient = ( (t_udbl) 1 << biL ) - 1;
1267
1268 if( r != NULL )
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001269 *r = (t_uint)( dividend - (quotient * d ) );
Simon Butchere4ed3472015-12-22 15:26:57 +00001270
1271 return (t_uint) quotient;
1272#else
Simon Butchere4ed3472015-12-22 15:26:57 +00001273
1274 /*
1275 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1276 * Vol. 2 - Seminumerical Algorithms, Knuth
1277 */
1278
1279 /*
1280 * Normalize the divisor, d, and dividend, u0, u1
1281 */
1282 s = int_clz( d );
1283 d = d << s;
1284
1285 u1 = u1 << s;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001286 u1 |= ( u0 >> ( biL - s ) ) & ( -(t_sint)s >> ( biL - 1 ) );
Simon Butchere4ed3472015-12-22 15:26:57 +00001287 u0 = u0 << s;
1288
1289 d1 = d >> biH;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001290 d0 = d & uint_halfword_mask;
Simon Butchere4ed3472015-12-22 15:26:57 +00001291
1292 u0_msw = u0 >> biH;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001293 u0_lsw = u0 & uint_halfword_mask;
Simon Butchere4ed3472015-12-22 15:26:57 +00001294
1295 /*
1296 * Find the first quotient and remainder
1297 */
1298 q1 = u1 / d1;
1299 r0 = u1 - d1 * q1;
1300
1301 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1302 {
1303 q1 -= 1;
1304 r0 += d1;
1305
1306 if ( r0 >= radix ) break;
1307 }
1308
Simon Butcher14400c82016-01-02 00:08:13 +00001309 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butchere4ed3472015-12-22 15:26:57 +00001310 q0 = rAX / d1;
1311 r0 = rAX - q0 * d1;
1312
1313 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1314 {
1315 q0 -= 1;
1316 r0 += d1;
1317
1318 if ( r0 >= radix ) break;
1319 }
1320
1321 if (r != NULL)
Simon Butcher14400c82016-01-02 00:08:13 +00001322 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butchere4ed3472015-12-22 15:26:57 +00001323
1324 quotient = q1 * radix + q0;
1325
1326 return quotient;
1327#endif
1328}
1329
1330/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001331 * Division by mpi: A = Q * B + R (HAC 14.20)
1332 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001333int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001334{
Paul Bakker23986e52011-04-24 08:57:21 +00001335 int ret;
1336 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001337 mpi X, Y, Z, T1, T2;
1338
1339 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001340 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001341
Paul Bakker6c591fa2011-05-05 11:49:20 +00001342 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1343 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001344
1345 if( mpi_cmp_abs( A, B ) < 0 )
1346 {
1347 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1348 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1349 return( 0 );
1350 }
1351
1352 MPI_CHK( mpi_copy( &X, A ) );
1353 MPI_CHK( mpi_copy( &Y, B ) );
1354 X.s = Y.s = 1;
1355
1356 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1357 MPI_CHK( mpi_lset( &Z, 0 ) );
1358 MPI_CHK( mpi_grow( &T1, 2 ) );
1359 MPI_CHK( mpi_grow( &T2, 3 ) );
1360
1361 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001362 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001363 {
1364 k = biL - 1 - k;
1365 MPI_CHK( mpi_shift_l( &X, k ) );
1366 MPI_CHK( mpi_shift_l( &Y, k ) );
1367 }
1368 else k = 0;
1369
1370 n = X.n - 1;
1371 t = Y.n - 1;
Paul Bakker66d5d072014-06-17 16:39:18 +02001372 MPI_CHK( mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001373
1374 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1375 {
1376 Z.p[n - t]++;
Paul Bakker6ea1a952013-12-31 11:16:03 +01001377 MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001378 }
Paul Bakker66d5d072014-06-17 16:39:18 +02001379 MPI_CHK( mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001380
1381 for( i = n; i > t ; i-- )
1382 {
1383 if( X.p[i] >= Y.p[t] )
1384 Z.p[i - t - 1] = ~0;
1385 else
1386 {
Simon Butchere4ed3472015-12-22 15:26:57 +00001387 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 +00001388 }
1389
1390 Z.p[i - t - 1]++;
1391 do
1392 {
1393 Z.p[i - t - 1]--;
1394
1395 MPI_CHK( mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001396 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001397 T1.p[1] = Y.p[t];
1398 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1399
1400 MPI_CHK( mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001401 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1402 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001403 T2.p[2] = X.p[i];
1404 }
1405 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1406
1407 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001408 MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001409 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1410
1411 if( mpi_cmp_int( &X, 0 ) < 0 )
1412 {
1413 MPI_CHK( mpi_copy( &T1, &Y ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001414 MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001415 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1416 Z.p[i - t - 1]--;
1417 }
1418 }
1419
1420 if( Q != NULL )
1421 {
Paul Bakker6ea1a952013-12-31 11:16:03 +01001422 MPI_CHK( mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001423 Q->s = A->s * B->s;
1424 }
1425
1426 if( R != NULL )
1427 {
Paul Bakker6ea1a952013-12-31 11:16:03 +01001428 MPI_CHK( mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001429 X.s = A->s;
Paul Bakker6ea1a952013-12-31 11:16:03 +01001430 MPI_CHK( mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001431
Paul Bakker5121ce52009-01-03 21:22:43 +00001432 if( mpi_cmp_int( R, 0 ) == 0 )
1433 R->s = 1;
1434 }
1435
1436cleanup:
1437
Paul Bakker6c591fa2011-05-05 11:49:20 +00001438 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1439 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001440
1441 return( ret );
1442}
1443
1444/*
1445 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001446 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001447int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001448{
1449 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001450 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001451
1452 p[0] = ( b < 0 ) ? -b : b;
1453 _B.s = ( b < 0 ) ? -1 : 1;
1454 _B.n = 1;
1455 _B.p = p;
1456
1457 return( mpi_div_mpi( Q, R, A, &_B ) );
1458}
1459
1460/*
1461 * Modulo: R = A mod B
1462 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001463int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001464{
1465 int ret;
1466
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001467 if( mpi_cmp_int( B, 0 ) < 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001468 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001469
Paul Bakker5121ce52009-01-03 21:22:43 +00001470 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1471
1472 while( mpi_cmp_int( R, 0 ) < 0 )
1473 MPI_CHK( mpi_add_mpi( R, R, B ) );
1474
1475 while( mpi_cmp_mpi( R, B ) >= 0 )
1476 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1477
1478cleanup:
1479
1480 return( ret );
1481}
1482
1483/*
1484 * Modulo: r = A mod b
1485 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001486int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001487{
Paul Bakker23986e52011-04-24 08:57:21 +00001488 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001489 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001490
1491 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001492 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001493
1494 if( b < 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001495 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001496
1497 /*
1498 * handle trivial cases
1499 */
1500 if( b == 1 )
1501 {
1502 *r = 0;
1503 return( 0 );
1504 }
1505
1506 if( b == 2 )
1507 {
1508 *r = A->p[0] & 1;
1509 return( 0 );
1510 }
1511
1512 /*
1513 * general case
1514 */
Paul Bakker23986e52011-04-24 08:57:21 +00001515 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001516 {
Paul Bakker23986e52011-04-24 08:57:21 +00001517 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001518 y = ( y << biH ) | ( x >> biH );
1519 z = y / b;
1520 y -= z * b;
1521
1522 x <<= biH;
1523 y = ( y << biH ) | ( x >> biH );
1524 z = y / b;
1525 y -= z * b;
1526 }
1527
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001528 /*
1529 * If A is negative, then the current y represents a negative value.
1530 * Flipping it to the positive side.
1531 */
1532 if( A->s < 0 && y != 0 )
1533 y = b - y;
1534
Paul Bakker5121ce52009-01-03 21:22:43 +00001535 *r = y;
1536
1537 return( 0 );
1538}
1539
1540/*
1541 * Fast Montgomery initialization (thanks to Tom St Denis)
1542 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001543static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001544{
Paul Bakkera755ca12011-04-24 09:11:17 +00001545 t_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001546 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001547
1548 x = m0;
1549 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001550
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001551 for( i = biL; i >= 8; i /= 2 )
1552 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001553
1554 *mm = ~x + 1;
1555}
1556
1557/*
1558 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1559 */
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02001560static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm,
1561 const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001562{
Paul Bakker23986e52011-04-24 08:57:21 +00001563 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001564 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001565
1566 memset( T->p, 0, T->n * ciL );
1567
1568 d = T->p;
1569 n = N->n;
1570 m = ( B->n < n ) ? B->n : n;
1571
1572 for( i = 0; i < n; i++ )
1573 {
1574 /*
1575 * T = (T + u0*B + u1*N) / 2^biL
1576 */
1577 u0 = A->p[i];
1578 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1579
1580 mpi_mul_hlp( m, B->p, d, u0 );
1581 mpi_mul_hlp( n, N->p, d, u1 );
1582
1583 *d++ = u0; d[n + 1] = 0;
1584 }
1585
Paul Bakker66d5d072014-06-17 16:39:18 +02001586 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001587
1588 if( mpi_cmp_abs( A, N ) >= 0 )
1589 mpi_sub_hlp( n, N->p, A->p );
1590 else
1591 /* prevent timing attacks */
1592 mpi_sub_hlp( n, A->p, T->p );
1593}
1594
1595/*
1596 * Montgomery reduction: A = A * R^-1 mod N
1597 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001598static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001599{
Paul Bakkera755ca12011-04-24 09:11:17 +00001600 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001601 mpi U;
1602
Paul Bakker8ddb6452013-02-27 14:56:33 +01001603 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001604 U.p = &z;
1605
1606 mpi_montmul( A, &U, N, mm, T );
1607}
1608
1609/*
1610 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1611 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001612int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001613{
Paul Bakker23986e52011-04-24 08:57:21 +00001614 int ret;
1615 size_t wbits, wsize, one = 1;
1616 size_t i, j, nblimbs;
1617 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001618 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001619 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1620 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001621
1622 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001623 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001624
Paul Bakkerf6198c12012-05-16 08:02:29 +00001625 if( mpi_cmp_int( E, 0 ) < 0 )
1626 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1627
1628 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001629 * Init temps and window size
1630 */
1631 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001632 mpi_init( &RR ); mpi_init( &T );
Manuel Pégourié-Gonnardfd6a1912014-01-18 19:05:23 +01001633 mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001634 memset( W, 0, sizeof( W ) );
1635
1636 i = mpi_msb( E );
1637
1638 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1639 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1640
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001641 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1642 wsize = POLARSSL_MPI_WINDOW_SIZE;
1643
Paul Bakker5121ce52009-01-03 21:22:43 +00001644 j = N->n + 1;
1645 MPI_CHK( mpi_grow( X, j ) );
1646 MPI_CHK( mpi_grow( &W[1], j ) );
1647 MPI_CHK( mpi_grow( &T, j * 2 ) );
1648
1649 /*
Paul Bakker50546922012-05-19 08:40:49 +00001650 * Compensate for negative A (and correct at the end)
1651 */
1652 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001653 if( neg )
1654 {
1655 MPI_CHK( mpi_copy( &Apos, A ) );
1656 Apos.s = 1;
1657 A = &Apos;
1658 }
1659
1660 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001661 * If 1st call, pre-compute R^2 mod N
1662 */
1663 if( _RR == NULL || _RR->p == NULL )
1664 {
1665 MPI_CHK( mpi_lset( &RR, 1 ) );
1666 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1667 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1668
1669 if( _RR != NULL )
1670 memcpy( _RR, &RR, sizeof( mpi ) );
1671 }
1672 else
1673 memcpy( &RR, _RR, sizeof( mpi ) );
1674
1675 /*
1676 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1677 */
1678 if( mpi_cmp_mpi( A, N ) >= 0 )
Paul Bakkerc2024f42014-01-23 20:38:35 +01001679 MPI_CHK( mpi_mod_mpi( &W[1], A, N ) );
1680 else
1681 MPI_CHK( mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001682
1683 mpi_montmul( &W[1], &RR, N, mm, &T );
1684
1685 /*
1686 * X = R^2 * R^-1 mod N = R mod N
1687 */
1688 MPI_CHK( mpi_copy( X, &RR ) );
1689 mpi_montred( X, N, mm, &T );
1690
1691 if( wsize > 1 )
1692 {
1693 /*
1694 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1695 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001696 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001697
1698 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1699 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1700
1701 for( i = 0; i < wsize - 1; i++ )
1702 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001703
Paul Bakker5121ce52009-01-03 21:22:43 +00001704 /*
1705 * W[i] = W[i - 1] * W[1]
1706 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001707 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001708 {
1709 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1710 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1711
1712 mpi_montmul( &W[i], &W[1], N, mm, &T );
1713 }
1714 }
1715
1716 nblimbs = E->n;
1717 bufsize = 0;
1718 nbits = 0;
1719 wbits = 0;
1720 state = 0;
1721
1722 while( 1 )
1723 {
1724 if( bufsize == 0 )
1725 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001726 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001727 break;
1728
Paul Bakker0d7702c2013-10-29 16:18:35 +01001729 nblimbs--;
1730
Paul Bakkera755ca12011-04-24 09:11:17 +00001731 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001732 }
1733
1734 bufsize--;
1735
1736 ei = (E->p[nblimbs] >> bufsize) & 1;
1737
1738 /*
1739 * skip leading 0s
1740 */
1741 if( ei == 0 && state == 0 )
1742 continue;
1743
1744 if( ei == 0 && state == 1 )
1745 {
1746 /*
1747 * out of window, square X
1748 */
1749 mpi_montmul( X, X, N, mm, &T );
1750 continue;
1751 }
1752
1753 /*
1754 * add ei to current window
1755 */
1756 state = 2;
1757
1758 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001759 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001760
1761 if( nbits == wsize )
1762 {
1763 /*
1764 * X = X^wsize R^-1 mod N
1765 */
1766 for( i = 0; i < wsize; i++ )
1767 mpi_montmul( X, X, N, mm, &T );
1768
1769 /*
1770 * X = X * W[wbits] R^-1 mod N
1771 */
1772 mpi_montmul( X, &W[wbits], N, mm, &T );
1773
1774 state--;
1775 nbits = 0;
1776 wbits = 0;
1777 }
1778 }
1779
1780 /*
1781 * process the remaining bits
1782 */
1783 for( i = 0; i < nbits; i++ )
1784 {
1785 mpi_montmul( X, X, N, mm, &T );
1786
1787 wbits <<= 1;
1788
Paul Bakker66d5d072014-06-17 16:39:18 +02001789 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001790 mpi_montmul( X, &W[1], N, mm, &T );
1791 }
1792
1793 /*
1794 * X = A^E * R * R^-1 mod N = A^E mod N
1795 */
1796 mpi_montred( X, N, mm, &T );
1797
Paul Bakkerf6198c12012-05-16 08:02:29 +00001798 if( neg )
1799 {
1800 X->s = -1;
Paul Bakkerc2024f42014-01-23 20:38:35 +01001801 MPI_CHK( mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001802 }
1803
Paul Bakker5121ce52009-01-03 21:22:43 +00001804cleanup:
1805
Paul Bakker66d5d072014-06-17 16:39:18 +02001806 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001807 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001808
Paul Bakkerf6198c12012-05-16 08:02:29 +00001809 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001810
Paul Bakker75a28602014-03-31 12:08:17 +02001811 if( _RR == NULL || _RR->p == NULL )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001812 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001813
1814 return( ret );
1815}
1816
Paul Bakker5121ce52009-01-03 21:22:43 +00001817/*
1818 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1819 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001820int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001821{
Paul Bakker23986e52011-04-24 08:57:21 +00001822 int ret;
1823 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001824 mpi TG, TA, TB;
1825
Paul Bakker6c591fa2011-05-05 11:49:20 +00001826 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001827
Paul Bakker5121ce52009-01-03 21:22:43 +00001828 MPI_CHK( mpi_copy( &TA, A ) );
1829 MPI_CHK( mpi_copy( &TB, B ) );
1830
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001831 lz = mpi_lsb( &TA );
1832 lzt = mpi_lsb( &TB );
1833
Paul Bakker66d5d072014-06-17 16:39:18 +02001834 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001835 lz = lzt;
1836
1837 MPI_CHK( mpi_shift_r( &TA, lz ) );
1838 MPI_CHK( mpi_shift_r( &TB, lz ) );
1839
Paul Bakker5121ce52009-01-03 21:22:43 +00001840 TA.s = TB.s = 1;
1841
1842 while( mpi_cmp_int( &TA, 0 ) != 0 )
1843 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001844 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1845 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846
1847 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1848 {
1849 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1850 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1851 }
1852 else
1853 {
1854 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1855 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1856 }
1857 }
1858
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001859 MPI_CHK( mpi_shift_l( &TB, lz ) );
1860 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001861
1862cleanup:
1863
Paul Bakker6c591fa2011-05-05 11:49:20 +00001864 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001865
1866 return( ret );
1867}
1868
Paul Bakker33dc46b2014-04-30 16:11:39 +02001869/*
1870 * Fill X with size bytes of random.
1871 *
1872 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001873 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001874 * deterministic, eg for tests).
1875 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001876int mpi_fill_random( mpi *X, size_t size,
1877 int (*f_rng)(void *, unsigned char *, size_t),
1878 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001879{
Paul Bakker23986e52011-04-24 08:57:21 +00001880 int ret;
Paul Bakker33dc46b2014-04-30 16:11:39 +02001881 unsigned char buf[POLARSSL_MPI_MAX_SIZE];
1882
1883 if( size > POLARSSL_MPI_MAX_SIZE )
1884 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001885
Paul Bakker33dc46b2014-04-30 16:11:39 +02001886 MPI_CHK( f_rng( p_rng, buf, size ) );
1887 MPI_CHK( mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001888
1889cleanup:
1890 return( ret );
1891}
1892
Paul Bakker5121ce52009-01-03 21:22:43 +00001893/*
1894 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1895 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001896int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001897{
1898 int ret;
1899 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1900
1901 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001902 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001903
Paul Bakker6c591fa2011-05-05 11:49:20 +00001904 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1905 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1906 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001907
1908 MPI_CHK( mpi_gcd( &G, A, N ) );
1909
1910 if( mpi_cmp_int( &G, 1 ) != 0 )
1911 {
Paul Bakker40e46942009-01-03 21:51:57 +00001912 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001913 goto cleanup;
1914 }
1915
1916 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1917 MPI_CHK( mpi_copy( &TU, &TA ) );
1918 MPI_CHK( mpi_copy( &TB, N ) );
1919 MPI_CHK( mpi_copy( &TV, N ) );
1920
1921 MPI_CHK( mpi_lset( &U1, 1 ) );
1922 MPI_CHK( mpi_lset( &U2, 0 ) );
1923 MPI_CHK( mpi_lset( &V1, 0 ) );
1924 MPI_CHK( mpi_lset( &V2, 1 ) );
1925
1926 do
1927 {
1928 while( ( TU.p[0] & 1 ) == 0 )
1929 {
1930 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1931
1932 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1933 {
1934 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1935 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1936 }
1937
1938 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1939 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1940 }
1941
1942 while( ( TV.p[0] & 1 ) == 0 )
1943 {
1944 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1945
1946 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1947 {
1948 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1949 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1950 }
1951
1952 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1953 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1954 }
1955
1956 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1957 {
1958 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1959 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1960 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1961 }
1962 else
1963 {
1964 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1965 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1966 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1967 }
1968 }
1969 while( mpi_cmp_int( &TU, 0 ) != 0 );
1970
1971 while( mpi_cmp_int( &V1, 0 ) < 0 )
1972 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1973
1974 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1975 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1976
1977 MPI_CHK( mpi_copy( X, &V1 ) );
1978
1979cleanup:
1980
Paul Bakker6c591fa2011-05-05 11:49:20 +00001981 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1982 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1983 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001984
1985 return( ret );
1986}
1987
Paul Bakkerd9374b02012-11-02 11:02:58 +00001988#if defined(POLARSSL_GENPRIME)
1989
Paul Bakker5121ce52009-01-03 21:22:43 +00001990static const int small_prime[] =
1991{
1992 3, 5, 7, 11, 13, 17, 19, 23,
1993 29, 31, 37, 41, 43, 47, 53, 59,
1994 61, 67, 71, 73, 79, 83, 89, 97,
1995 101, 103, 107, 109, 113, 127, 131, 137,
1996 139, 149, 151, 157, 163, 167, 173, 179,
1997 181, 191, 193, 197, 199, 211, 223, 227,
1998 229, 233, 239, 241, 251, 257, 263, 269,
1999 271, 277, 281, 283, 293, 307, 311, 313,
2000 317, 331, 337, 347, 349, 353, 359, 367,
2001 373, 379, 383, 389, 397, 401, 409, 419,
2002 421, 431, 433, 439, 443, 449, 457, 461,
2003 463, 467, 479, 487, 491, 499, 503, 509,
2004 521, 523, 541, 547, 557, 563, 569, 571,
2005 577, 587, 593, 599, 601, 607, 613, 617,
2006 619, 631, 641, 643, 647, 653, 659, 661,
2007 673, 677, 683, 691, 701, 709, 719, 727,
2008 733, 739, 743, 751, 757, 761, 769, 773,
2009 787, 797, 809, 811, 821, 823, 827, 829,
2010 839, 853, 857, 859, 863, 877, 881, 883,
2011 887, 907, 911, 919, 929, 937, 941, 947,
2012 953, 967, 971, 977, 983, 991, 997, -103
2013};
2014
2015/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002016 * Small divisors test (X must be positive)
2017 *
2018 * Return values:
2019 * 0: no small factor (possible prime, more tests needed)
2020 * 1: certain prime
2021 * POLARSSL_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2022 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002023 */
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002024static int mpi_check_small_factors( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002025{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002026 int ret = 0;
2027 size_t i;
2028 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002029
Paul Bakker5121ce52009-01-03 21:22:43 +00002030 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002031 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002032
2033 for( i = 0; small_prime[i] > 0; i++ )
2034 {
Paul Bakker5121ce52009-01-03 21:22:43 +00002035 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002036 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002037
2038 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
2039
2040 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002041 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002042 }
2043
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002044cleanup:
2045 return( ret );
2046}
2047
2048/*
2049 * Miller-Rabin pseudo-primality test (HAC 4.24)
2050 */
2051static int mpi_miller_rabin( const mpi *X,
2052 int (*f_rng)(void *, unsigned char *, size_t),
2053 void *p_rng )
2054{
Pascal Junodb99183d2015-03-11 16:49:45 +01002055 int ret, count;
2056 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002057 mpi W, R, T, A, RR;
2058
2059 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
2060 mpi_init( &RR );
2061
Paul Bakker5121ce52009-01-03 21:22:43 +00002062 /*
2063 * W = |X| - 1
2064 * R = W >> lsb( W )
2065 */
Paul Bakker5121ce52009-01-03 21:22:43 +00002066 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00002067 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00002068 MPI_CHK( mpi_copy( &R, &W ) );
2069 MPI_CHK( mpi_shift_r( &R, s ) );
2070
2071 i = mpi_msb( X );
2072 /*
2073 * HAC, table 4.4
2074 */
2075 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2076 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2077 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2078
2079 for( i = 0; i < n; i++ )
2080 {
2081 /*
2082 * pick a random A, 1 < A < |X| - 1
2083 */
Paul Bakker5121ce52009-01-03 21:22:43 +00002084
Pascal Junodb99183d2015-03-11 16:49:45 +01002085 count = 0;
2086 do {
2087 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
2088
2089 j = mpi_msb( &A );
2090 k = mpi_msb( &W );
2091 if (j > k) {
2092 MPI_CHK( mpi_shift_r( &A, j - k ) );
2093 }
2094
2095 if (count++ > 30) {
2096 return POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
2097 }
2098
2099 } while ( (mpi_cmp_mpi( &A, &W ) >= 0) ||
2100 (mpi_cmp_int( &A, 1 ) <= 0) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002101
2102 /*
2103 * A = A^R mod |X|
2104 */
2105 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
2106
2107 if( mpi_cmp_mpi( &A, &W ) == 0 ||
2108 mpi_cmp_int( &A, 1 ) == 0 )
2109 continue;
2110
2111 j = 1;
2112 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
2113 {
2114 /*
2115 * A = A * A mod |X|
2116 */
2117 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
2118 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
2119
2120 if( mpi_cmp_int( &A, 1 ) == 0 )
2121 break;
2122
2123 j++;
2124 }
2125
2126 /*
2127 * not prime if A != |X| - 1 or A == 1
2128 */
2129 if( mpi_cmp_mpi( &A, &W ) != 0 ||
2130 mpi_cmp_int( &A, 1 ) == 0 )
2131 {
Paul Bakker40e46942009-01-03 21:51:57 +00002132 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002133 break;
2134 }
2135 }
2136
2137cleanup:
Paul Bakker6c591fa2011-05-05 11:49:20 +00002138 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
2139 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002140
2141 return( ret );
2142}
2143
2144/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002145 * Pseudo-primality test: small factors, then Miller-Rabin
2146 */
Paul Bakker45f457d2013-11-25 14:26:52 +01002147int mpi_is_prime( mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002148 int (*f_rng)(void *, unsigned char *, size_t),
2149 void *p_rng )
2150{
2151 int ret;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002152 mpi XX;
2153
2154 XX.s = 1;
2155 XX.n = X->n;
2156 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002157
2158 if( mpi_cmp_int( &XX, 0 ) == 0 ||
2159 mpi_cmp_int( &XX, 1 ) == 0 )
2160 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
2161
2162 if( mpi_cmp_int( &XX, 2 ) == 0 )
2163 return( 0 );
2164
2165 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2166 {
2167 if( ret == 1 )
2168 return( 0 );
2169
2170 return( ret );
2171 }
2172
2173 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2174}
2175
2176/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002177 * Prime number generation
2178 */
Paul Bakker23986e52011-04-24 08:57:21 +00002179int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002180 int (*f_rng)(void *, unsigned char *, size_t),
2181 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002182{
Paul Bakker23986e52011-04-24 08:57:21 +00002183 int ret;
2184 size_t k, n;
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002185 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002186 mpi Y;
2187
Paul Bakkerfe3256e2011-11-25 12:11:43 +00002188 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00002189 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002190
Paul Bakker6c591fa2011-05-05 11:49:20 +00002191 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002192
2193 n = BITS_TO_LIMBS( nbits );
2194
Paul Bakker901c6562012-04-20 13:25:38 +00002195 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002196
2197 k = mpi_msb( X );
Pascal Junodb99183d2015-03-11 16:49:45 +01002198 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002199
Pascal Junodb99183d2015-03-11 16:49:45 +01002200 mpi_set_bit( X, nbits-1, 1 );
2201
2202 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002203
2204 if( dh_flag == 0 )
2205 {
2206 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
2207 {
Paul Bakker40e46942009-01-03 21:51:57 +00002208 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002209 goto cleanup;
2210
2211 MPI_CHK( mpi_add_int( X, X, 2 ) );
2212 }
2213 }
2214 else
2215 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002216 /*
2217 * An necessary condition for Y and X = 2Y + 1 to be prime
2218 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2219 * Make sure it is satisfied, while keeping X = 3 mod 4
2220 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002221
2222 X->p[0] |= 2;
2223
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002224 MPI_CHK( mpi_mod_int( &r, X, 3 ) );
2225 if( r == 0 )
2226 MPI_CHK( mpi_add_int( X, X, 8 ) );
2227 else if( r == 1 )
2228 MPI_CHK( mpi_add_int( X, X, 4 ) );
2229
2230 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2231 MPI_CHK( mpi_copy( &Y, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002232 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2233
2234 while( 1 )
2235 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002236 /*
2237 * First, check small factors for X and Y
2238 * before doing Miller-Rabin on any of them
2239 */
2240 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2241 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2242 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2243 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002244 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002245 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002246 }
2247
Paul Bakker40e46942009-01-03 21:51:57 +00002248 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002249 goto cleanup;
2250
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002251 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002252 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002253 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2254 * so up Y by 6 and X by 12.
2255 */
2256 MPI_CHK( mpi_add_int( X, X, 12 ) );
2257 MPI_CHK( mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002258 }
2259 }
2260
2261cleanup:
2262
Paul Bakker6c591fa2011-05-05 11:49:20 +00002263 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002264
2265 return( ret );
2266}
2267
Manuel Pégourié-Gonnarddf0142b2013-08-22 18:29:07 +02002268#endif /* POLARSSL_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002269
Paul Bakker40e46942009-01-03 21:51:57 +00002270#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002271
Paul Bakker23986e52011-04-24 08:57:21 +00002272#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002273
2274static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2275{
2276 { 693, 609, 21 },
2277 { 1764, 868, 28 },
2278 { 768454923, 542167814, 1 }
2279};
2280
Paul Bakker5121ce52009-01-03 21:22:43 +00002281/*
2282 * Checkup routine
2283 */
2284int mpi_self_test( int verbose )
2285{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002286 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002287 mpi A, E, N, X, Y, U, V;
2288
Paul Bakker6c591fa2011-05-05 11:49:20 +00002289 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2290 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002291
2292 MPI_CHK( mpi_read_string( &A, 16,
2293 "EFE021C2645FD1DC586E69184AF4A31E" \
2294 "D5F53E93B5F123FA41680867BA110131" \
2295 "944FE7952E2517337780CB0DB80E61AA" \
2296 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2297
2298 MPI_CHK( mpi_read_string( &E, 16,
2299 "B2E7EFD37075B9F03FF989C7C5051C20" \
2300 "34D2A323810251127E7BF8625A4F49A5" \
2301 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2302 "5B5C25763222FEFCCFC38B832366C29E" ) );
2303
2304 MPI_CHK( mpi_read_string( &N, 16,
2305 "0066A198186C18C10B2F5ED9B522752A" \
2306 "9830B69916E535C8F047518A889A43A5" \
2307 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2308
2309 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2310
2311 MPI_CHK( mpi_read_string( &U, 16,
2312 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2313 "9E857EA95A03512E2BAE7391688D264A" \
2314 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2315 "8001B72E848A38CAE1C65F78E56ABDEF" \
2316 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2317 "ECF677152EF804370C1A305CAF3B5BF1" \
2318 "30879B56C61DE584A0F53A2447A51E" ) );
2319
2320 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002321 polarssl_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002322
2323 if( mpi_cmp_mpi( &X, &U ) != 0 )
2324 {
2325 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002326 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002327
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002328 ret = 1;
2329 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002330 }
2331
2332 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002333 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002334
2335 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2336
2337 MPI_CHK( mpi_read_string( &U, 16,
2338 "256567336059E52CAE22925474705F39A94" ) );
2339
2340 MPI_CHK( mpi_read_string( &V, 16,
2341 "6613F26162223DF488E9CD48CC132C7A" \
2342 "0AC93C701B001B092E4E5B9F73BCD27B" \
2343 "9EE50D0657C77F374E903CDFA4C642" ) );
2344
2345 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002346 polarssl_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002347
2348 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2349 mpi_cmp_mpi( &Y, &V ) != 0 )
2350 {
2351 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002352 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002353
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002354 ret = 1;
2355 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002356 }
2357
2358 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002359 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
2361 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2362
2363 MPI_CHK( mpi_read_string( &U, 16,
2364 "36E139AEA55215609D2816998ED020BB" \
2365 "BD96C37890F65171D948E9BC7CBAA4D9" \
2366 "325D24D6A3C12710F10A09FA08AB87" ) );
2367
2368 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002369 polarssl_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002370
2371 if( mpi_cmp_mpi( &X, &U ) != 0 )
2372 {
2373 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002374 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002375
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002376 ret = 1;
2377 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002378 }
2379
2380 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002381 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002382
2383 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2384
2385 MPI_CHK( mpi_read_string( &U, 16,
2386 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2387 "C3DBA76456363A10869622EAC2DD84EC" \
2388 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2389
2390 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002391 polarssl_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002392
2393 if( mpi_cmp_mpi( &X, &U ) != 0 )
2394 {
2395 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002396 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002397
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002398 ret = 1;
2399 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002400 }
2401
2402 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002403 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002404
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002405 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002406 polarssl_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002407
Paul Bakker66d5d072014-06-17 16:39:18 +02002408 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002409 {
2410 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002411 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002412
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002413 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002414
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002415 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2416 {
2417 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002418 polarssl_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002419
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002420 ret = 1;
2421 goto cleanup;
2422 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002423 }
2424
2425 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002426 polarssl_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002427
Paul Bakker5121ce52009-01-03 21:22:43 +00002428cleanup:
2429
2430 if( ret != 0 && verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002431 polarssl_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002432
Paul Bakker6c591fa2011-05-05 11:49:20 +00002433 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2434 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002435
2436 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002437 polarssl_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002438
2439 return( ret );
2440}
2441
Paul Bakker9af723c2014-05-01 13:03:14 +02002442#endif /* POLARSSL_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002443
Paul Bakker9af723c2014-05-01 13:03:14 +02002444#endif /* POLARSSL_BIGNUM_C */