blob: 89fbe12c4cc8893307605b909fabecec2a9d0b86 [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
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001229 const t_uint radix = (t_uint) 1 << biH;
1230 const t_uint uint_halfword_mask = ( (t_uint) 1 << biH ) - 1;
Simon Butcher14400c82016-01-02 00:08:13 +00001231 t_uint d0, d1, q0, q1, rAX, r0, quotient;
1232 t_uint u0_msw, u0_lsw;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001233 size_t s;
Simon Butchere4ed3472015-12-22 15:26:57 +00001234#endif
1235
1236 /*
1237 * Check for overflow
1238 */
Simon Butcher14400c82016-01-02 00:08:13 +00001239 if( 0 == d || u1 >= d )
Simon Butchere4ed3472015-12-22 15:26:57 +00001240 {
Simon Butcher14400c82016-01-02 00:08:13 +00001241 if ( r != NULL ) *r = ~0;
Simon Butchere4ed3472015-12-22 15:26:57 +00001242
Simon Butcher14400c82016-01-02 00:08:13 +00001243 return ( ~0 );
Simon Butchere4ed3472015-12-22 15:26:57 +00001244 }
1245
1246#if defined(POLARSSL_HAVE_UDBL)
1247 dividend = (t_udbl) u1 << biL;
1248 dividend |= (t_udbl) u0;
1249 quotient = dividend / d;
1250 if( quotient > ( (t_udbl) 1 << biL ) - 1 )
1251 quotient = ( (t_udbl) 1 << biL ) - 1;
1252
1253 if( r != NULL )
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001254 *r = (t_uint)( dividend - (quotient * d ) );
Simon Butchere4ed3472015-12-22 15:26:57 +00001255
1256 return (t_uint) quotient;
1257#else
Simon Butchere4ed3472015-12-22 15:26:57 +00001258
1259 /*
1260 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1261 * Vol. 2 - Seminumerical Algorithms, Knuth
1262 */
1263
1264 /*
1265 * Normalize the divisor, d, and dividend, u0, u1
1266 */
1267 s = int_clz( d );
1268 d = d << s;
1269
1270 u1 = u1 << s;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001271 u1 |= ( u0 >> ( biL - s ) ) & ( -(t_sint)s >> ( biL - 1 ) );
Simon Butchere4ed3472015-12-22 15:26:57 +00001272 u0 = u0 << s;
1273
1274 d1 = d >> biH;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001275 d0 = d & uint_halfword_mask;
Simon Butchere4ed3472015-12-22 15:26:57 +00001276
1277 u0_msw = u0 >> biH;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001278 u0_lsw = u0 & uint_halfword_mask;
Simon Butchere4ed3472015-12-22 15:26:57 +00001279
1280 /*
1281 * Find the first quotient and remainder
1282 */
1283 q1 = u1 / d1;
1284 r0 = u1 - d1 * q1;
1285
1286 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1287 {
1288 q1 -= 1;
1289 r0 += d1;
1290
1291 if ( r0 >= radix ) break;
1292 }
1293
Simon Butcher14400c82016-01-02 00:08:13 +00001294 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butchere4ed3472015-12-22 15:26:57 +00001295 q0 = rAX / d1;
1296 r0 = rAX - q0 * d1;
1297
1298 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1299 {
1300 q0 -= 1;
1301 r0 += d1;
1302
1303 if ( r0 >= radix ) break;
1304 }
1305
1306 if (r != NULL)
Simon Butcher14400c82016-01-02 00:08:13 +00001307 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butchere4ed3472015-12-22 15:26:57 +00001308
1309 quotient = q1 * radix + q0;
1310
1311 return quotient;
1312#endif
1313}
1314
1315/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001316 * Division by mpi: A = Q * B + R (HAC 14.20)
1317 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001318int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001319{
Paul Bakker23986e52011-04-24 08:57:21 +00001320 int ret;
1321 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001322 mpi X, Y, Z, T1, T2;
1323
1324 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001325 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001326
Paul Bakker6c591fa2011-05-05 11:49:20 +00001327 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1328 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001329
1330 if( mpi_cmp_abs( A, B ) < 0 )
1331 {
1332 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1333 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1334 return( 0 );
1335 }
1336
1337 MPI_CHK( mpi_copy( &X, A ) );
1338 MPI_CHK( mpi_copy( &Y, B ) );
1339 X.s = Y.s = 1;
1340
1341 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1342 MPI_CHK( mpi_lset( &Z, 0 ) );
1343 MPI_CHK( mpi_grow( &T1, 2 ) );
1344 MPI_CHK( mpi_grow( &T2, 3 ) );
1345
1346 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001347 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001348 {
1349 k = biL - 1 - k;
1350 MPI_CHK( mpi_shift_l( &X, k ) );
1351 MPI_CHK( mpi_shift_l( &Y, k ) );
1352 }
1353 else k = 0;
1354
1355 n = X.n - 1;
1356 t = Y.n - 1;
Paul Bakker66d5d072014-06-17 16:39:18 +02001357 MPI_CHK( mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001358
1359 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1360 {
1361 Z.p[n - t]++;
Paul Bakker6ea1a952013-12-31 11:16:03 +01001362 MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001363 }
Paul Bakker66d5d072014-06-17 16:39:18 +02001364 MPI_CHK( mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001365
1366 for( i = n; i > t ; i-- )
1367 {
1368 if( X.p[i] >= Y.p[t] )
1369 Z.p[i - t - 1] = ~0;
1370 else
1371 {
Simon Butchere4ed3472015-12-22 15:26:57 +00001372 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 +00001373 }
1374
1375 Z.p[i - t - 1]++;
1376 do
1377 {
1378 Z.p[i - t - 1]--;
1379
1380 MPI_CHK( mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001381 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001382 T1.p[1] = Y.p[t];
1383 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1384
1385 MPI_CHK( mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001386 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1387 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001388 T2.p[2] = X.p[i];
1389 }
1390 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1391
1392 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001393 MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001394 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1395
1396 if( mpi_cmp_int( &X, 0 ) < 0 )
1397 {
1398 MPI_CHK( mpi_copy( &T1, &Y ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001399 MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001400 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1401 Z.p[i - t - 1]--;
1402 }
1403 }
1404
1405 if( Q != NULL )
1406 {
Paul Bakker6ea1a952013-12-31 11:16:03 +01001407 MPI_CHK( mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001408 Q->s = A->s * B->s;
1409 }
1410
1411 if( R != NULL )
1412 {
Paul Bakker6ea1a952013-12-31 11:16:03 +01001413 MPI_CHK( mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001414 X.s = A->s;
Paul Bakker6ea1a952013-12-31 11:16:03 +01001415 MPI_CHK( mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001416
Paul Bakker5121ce52009-01-03 21:22:43 +00001417 if( mpi_cmp_int( R, 0 ) == 0 )
1418 R->s = 1;
1419 }
1420
1421cleanup:
1422
Paul Bakker6c591fa2011-05-05 11:49:20 +00001423 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1424 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001425
1426 return( ret );
1427}
1428
1429/*
1430 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001431 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001432int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001433{
1434 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001435 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001436
1437 p[0] = ( b < 0 ) ? -b : b;
1438 _B.s = ( b < 0 ) ? -1 : 1;
1439 _B.n = 1;
1440 _B.p = p;
1441
1442 return( mpi_div_mpi( Q, R, A, &_B ) );
1443}
1444
1445/*
1446 * Modulo: R = A mod B
1447 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001448int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001449{
1450 int ret;
1451
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001452 if( mpi_cmp_int( B, 0 ) < 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001453 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001454
Paul Bakker5121ce52009-01-03 21:22:43 +00001455 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1456
1457 while( mpi_cmp_int( R, 0 ) < 0 )
1458 MPI_CHK( mpi_add_mpi( R, R, B ) );
1459
1460 while( mpi_cmp_mpi( R, B ) >= 0 )
1461 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1462
1463cleanup:
1464
1465 return( ret );
1466}
1467
1468/*
1469 * Modulo: r = A mod b
1470 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001471int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001472{
Paul Bakker23986e52011-04-24 08:57:21 +00001473 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001474 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001475
1476 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001477 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001478
1479 if( b < 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001480 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001481
1482 /*
1483 * handle trivial cases
1484 */
1485 if( b == 1 )
1486 {
1487 *r = 0;
1488 return( 0 );
1489 }
1490
1491 if( b == 2 )
1492 {
1493 *r = A->p[0] & 1;
1494 return( 0 );
1495 }
1496
1497 /*
1498 * general case
1499 */
Paul Bakker23986e52011-04-24 08:57:21 +00001500 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001501 {
Paul Bakker23986e52011-04-24 08:57:21 +00001502 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001503 y = ( y << biH ) | ( x >> biH );
1504 z = y / b;
1505 y -= z * b;
1506
1507 x <<= biH;
1508 y = ( y << biH ) | ( x >> biH );
1509 z = y / b;
1510 y -= z * b;
1511 }
1512
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001513 /*
1514 * If A is negative, then the current y represents a negative value.
1515 * Flipping it to the positive side.
1516 */
1517 if( A->s < 0 && y != 0 )
1518 y = b - y;
1519
Paul Bakker5121ce52009-01-03 21:22:43 +00001520 *r = y;
1521
1522 return( 0 );
1523}
1524
1525/*
1526 * Fast Montgomery initialization (thanks to Tom St Denis)
1527 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001528static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001529{
Paul Bakkera755ca12011-04-24 09:11:17 +00001530 t_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001531 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001532
1533 x = m0;
1534 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001535
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001536 for( i = biL; i >= 8; i /= 2 )
1537 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001538
1539 *mm = ~x + 1;
1540}
1541
1542/*
1543 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1544 */
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02001545static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm,
1546 const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001547{
Paul Bakker23986e52011-04-24 08:57:21 +00001548 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001549 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001550
1551 memset( T->p, 0, T->n * ciL );
1552
1553 d = T->p;
1554 n = N->n;
1555 m = ( B->n < n ) ? B->n : n;
1556
1557 for( i = 0; i < n; i++ )
1558 {
1559 /*
1560 * T = (T + u0*B + u1*N) / 2^biL
1561 */
1562 u0 = A->p[i];
1563 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1564
1565 mpi_mul_hlp( m, B->p, d, u0 );
1566 mpi_mul_hlp( n, N->p, d, u1 );
1567
1568 *d++ = u0; d[n + 1] = 0;
1569 }
1570
Paul Bakker66d5d072014-06-17 16:39:18 +02001571 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001572
1573 if( mpi_cmp_abs( A, N ) >= 0 )
1574 mpi_sub_hlp( n, N->p, A->p );
1575 else
1576 /* prevent timing attacks */
1577 mpi_sub_hlp( n, A->p, T->p );
1578}
1579
1580/*
1581 * Montgomery reduction: A = A * R^-1 mod N
1582 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001583static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001584{
Paul Bakkera755ca12011-04-24 09:11:17 +00001585 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001586 mpi U;
1587
Paul Bakker8ddb6452013-02-27 14:56:33 +01001588 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001589 U.p = &z;
1590
1591 mpi_montmul( A, &U, N, mm, T );
1592}
1593
1594/*
1595 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1596 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001597int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001598{
Paul Bakker23986e52011-04-24 08:57:21 +00001599 int ret;
1600 size_t wbits, wsize, one = 1;
1601 size_t i, j, nblimbs;
1602 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001603 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001604 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1605 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001606
1607 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001608 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001609
Paul Bakkerf6198c12012-05-16 08:02:29 +00001610 if( mpi_cmp_int( E, 0 ) < 0 )
1611 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1612
1613 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001614 * Init temps and window size
1615 */
1616 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001617 mpi_init( &RR ); mpi_init( &T );
Manuel Pégourié-Gonnardfd6a1912014-01-18 19:05:23 +01001618 mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001619 memset( W, 0, sizeof( W ) );
1620
1621 i = mpi_msb( E );
1622
1623 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1624 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1625
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001626 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1627 wsize = POLARSSL_MPI_WINDOW_SIZE;
1628
Paul Bakker5121ce52009-01-03 21:22:43 +00001629 j = N->n + 1;
1630 MPI_CHK( mpi_grow( X, j ) );
1631 MPI_CHK( mpi_grow( &W[1], j ) );
1632 MPI_CHK( mpi_grow( &T, j * 2 ) );
1633
1634 /*
Paul Bakker50546922012-05-19 08:40:49 +00001635 * Compensate for negative A (and correct at the end)
1636 */
1637 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001638 if( neg )
1639 {
1640 MPI_CHK( mpi_copy( &Apos, A ) );
1641 Apos.s = 1;
1642 A = &Apos;
1643 }
1644
1645 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001646 * If 1st call, pre-compute R^2 mod N
1647 */
1648 if( _RR == NULL || _RR->p == NULL )
1649 {
1650 MPI_CHK( mpi_lset( &RR, 1 ) );
1651 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1652 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1653
1654 if( _RR != NULL )
1655 memcpy( _RR, &RR, sizeof( mpi ) );
1656 }
1657 else
1658 memcpy( &RR, _RR, sizeof( mpi ) );
1659
1660 /*
1661 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1662 */
1663 if( mpi_cmp_mpi( A, N ) >= 0 )
Paul Bakkerc2024f42014-01-23 20:38:35 +01001664 MPI_CHK( mpi_mod_mpi( &W[1], A, N ) );
1665 else
1666 MPI_CHK( mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001667
1668 mpi_montmul( &W[1], &RR, N, mm, &T );
1669
1670 /*
1671 * X = R^2 * R^-1 mod N = R mod N
1672 */
1673 MPI_CHK( mpi_copy( X, &RR ) );
1674 mpi_montred( X, N, mm, &T );
1675
1676 if( wsize > 1 )
1677 {
1678 /*
1679 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1680 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001681 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001682
1683 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1684 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1685
1686 for( i = 0; i < wsize - 1; i++ )
1687 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001688
Paul Bakker5121ce52009-01-03 21:22:43 +00001689 /*
1690 * W[i] = W[i - 1] * W[1]
1691 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001692 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001693 {
1694 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1695 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1696
1697 mpi_montmul( &W[i], &W[1], N, mm, &T );
1698 }
1699 }
1700
1701 nblimbs = E->n;
1702 bufsize = 0;
1703 nbits = 0;
1704 wbits = 0;
1705 state = 0;
1706
1707 while( 1 )
1708 {
1709 if( bufsize == 0 )
1710 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001711 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001712 break;
1713
Paul Bakker0d7702c2013-10-29 16:18:35 +01001714 nblimbs--;
1715
Paul Bakkera755ca12011-04-24 09:11:17 +00001716 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001717 }
1718
1719 bufsize--;
1720
1721 ei = (E->p[nblimbs] >> bufsize) & 1;
1722
1723 /*
1724 * skip leading 0s
1725 */
1726 if( ei == 0 && state == 0 )
1727 continue;
1728
1729 if( ei == 0 && state == 1 )
1730 {
1731 /*
1732 * out of window, square X
1733 */
1734 mpi_montmul( X, X, N, mm, &T );
1735 continue;
1736 }
1737
1738 /*
1739 * add ei to current window
1740 */
1741 state = 2;
1742
1743 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001744 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001745
1746 if( nbits == wsize )
1747 {
1748 /*
1749 * X = X^wsize R^-1 mod N
1750 */
1751 for( i = 0; i < wsize; i++ )
1752 mpi_montmul( X, X, N, mm, &T );
1753
1754 /*
1755 * X = X * W[wbits] R^-1 mod N
1756 */
1757 mpi_montmul( X, &W[wbits], N, mm, &T );
1758
1759 state--;
1760 nbits = 0;
1761 wbits = 0;
1762 }
1763 }
1764
1765 /*
1766 * process the remaining bits
1767 */
1768 for( i = 0; i < nbits; i++ )
1769 {
1770 mpi_montmul( X, X, N, mm, &T );
1771
1772 wbits <<= 1;
1773
Paul Bakker66d5d072014-06-17 16:39:18 +02001774 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001775 mpi_montmul( X, &W[1], N, mm, &T );
1776 }
1777
1778 /*
1779 * X = A^E * R * R^-1 mod N = A^E mod N
1780 */
1781 mpi_montred( X, N, mm, &T );
1782
Paul Bakkerf6198c12012-05-16 08:02:29 +00001783 if( neg )
1784 {
1785 X->s = -1;
Paul Bakkerc2024f42014-01-23 20:38:35 +01001786 MPI_CHK( mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001787 }
1788
Paul Bakker5121ce52009-01-03 21:22:43 +00001789cleanup:
1790
Paul Bakker66d5d072014-06-17 16:39:18 +02001791 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001792 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001793
Paul Bakkerf6198c12012-05-16 08:02:29 +00001794 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001795
Paul Bakker75a28602014-03-31 12:08:17 +02001796 if( _RR == NULL || _RR->p == NULL )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001797 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001798
1799 return( ret );
1800}
1801
Paul Bakker5121ce52009-01-03 21:22:43 +00001802/*
1803 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1804 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001805int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001806{
Paul Bakker23986e52011-04-24 08:57:21 +00001807 int ret;
1808 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001809 mpi TG, TA, TB;
1810
Paul Bakker6c591fa2011-05-05 11:49:20 +00001811 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001812
Paul Bakker5121ce52009-01-03 21:22:43 +00001813 MPI_CHK( mpi_copy( &TA, A ) );
1814 MPI_CHK( mpi_copy( &TB, B ) );
1815
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001816 lz = mpi_lsb( &TA );
1817 lzt = mpi_lsb( &TB );
1818
Paul Bakker66d5d072014-06-17 16:39:18 +02001819 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001820 lz = lzt;
1821
1822 MPI_CHK( mpi_shift_r( &TA, lz ) );
1823 MPI_CHK( mpi_shift_r( &TB, lz ) );
1824
Paul Bakker5121ce52009-01-03 21:22:43 +00001825 TA.s = TB.s = 1;
1826
1827 while( mpi_cmp_int( &TA, 0 ) != 0 )
1828 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001829 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1830 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001831
1832 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1833 {
1834 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1835 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1836 }
1837 else
1838 {
1839 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1840 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1841 }
1842 }
1843
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001844 MPI_CHK( mpi_shift_l( &TB, lz ) );
1845 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846
1847cleanup:
1848
Paul Bakker6c591fa2011-05-05 11:49:20 +00001849 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001850
1851 return( ret );
1852}
1853
Paul Bakker33dc46b2014-04-30 16:11:39 +02001854/*
1855 * Fill X with size bytes of random.
1856 *
1857 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001858 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001859 * deterministic, eg for tests).
1860 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001861int mpi_fill_random( mpi *X, size_t size,
1862 int (*f_rng)(void *, unsigned char *, size_t),
1863 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001864{
Paul Bakker23986e52011-04-24 08:57:21 +00001865 int ret;
Paul Bakker33dc46b2014-04-30 16:11:39 +02001866 unsigned char buf[POLARSSL_MPI_MAX_SIZE];
1867
1868 if( size > POLARSSL_MPI_MAX_SIZE )
1869 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001870
Paul Bakker33dc46b2014-04-30 16:11:39 +02001871 MPI_CHK( f_rng( p_rng, buf, size ) );
1872 MPI_CHK( mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001873
1874cleanup:
1875 return( ret );
1876}
1877
Paul Bakker5121ce52009-01-03 21:22:43 +00001878/*
1879 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1880 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001881int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001882{
1883 int ret;
1884 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1885
1886 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001887 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001888
Paul Bakker6c591fa2011-05-05 11:49:20 +00001889 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1890 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1891 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001892
1893 MPI_CHK( mpi_gcd( &G, A, N ) );
1894
1895 if( mpi_cmp_int( &G, 1 ) != 0 )
1896 {
Paul Bakker40e46942009-01-03 21:51:57 +00001897 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001898 goto cleanup;
1899 }
1900
1901 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1902 MPI_CHK( mpi_copy( &TU, &TA ) );
1903 MPI_CHK( mpi_copy( &TB, N ) );
1904 MPI_CHK( mpi_copy( &TV, N ) );
1905
1906 MPI_CHK( mpi_lset( &U1, 1 ) );
1907 MPI_CHK( mpi_lset( &U2, 0 ) );
1908 MPI_CHK( mpi_lset( &V1, 0 ) );
1909 MPI_CHK( mpi_lset( &V2, 1 ) );
1910
1911 do
1912 {
1913 while( ( TU.p[0] & 1 ) == 0 )
1914 {
1915 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1916
1917 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1918 {
1919 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1920 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1921 }
1922
1923 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1924 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1925 }
1926
1927 while( ( TV.p[0] & 1 ) == 0 )
1928 {
1929 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1930
1931 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1932 {
1933 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1934 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1935 }
1936
1937 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1938 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1939 }
1940
1941 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1942 {
1943 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1944 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1945 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1946 }
1947 else
1948 {
1949 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1950 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1951 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1952 }
1953 }
1954 while( mpi_cmp_int( &TU, 0 ) != 0 );
1955
1956 while( mpi_cmp_int( &V1, 0 ) < 0 )
1957 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1958
1959 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1960 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1961
1962 MPI_CHK( mpi_copy( X, &V1 ) );
1963
1964cleanup:
1965
Paul Bakker6c591fa2011-05-05 11:49:20 +00001966 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1967 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1968 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
1970 return( ret );
1971}
1972
Paul Bakkerd9374b02012-11-02 11:02:58 +00001973#if defined(POLARSSL_GENPRIME)
1974
Paul Bakker5121ce52009-01-03 21:22:43 +00001975static const int small_prime[] =
1976{
1977 3, 5, 7, 11, 13, 17, 19, 23,
1978 29, 31, 37, 41, 43, 47, 53, 59,
1979 61, 67, 71, 73, 79, 83, 89, 97,
1980 101, 103, 107, 109, 113, 127, 131, 137,
1981 139, 149, 151, 157, 163, 167, 173, 179,
1982 181, 191, 193, 197, 199, 211, 223, 227,
1983 229, 233, 239, 241, 251, 257, 263, 269,
1984 271, 277, 281, 283, 293, 307, 311, 313,
1985 317, 331, 337, 347, 349, 353, 359, 367,
1986 373, 379, 383, 389, 397, 401, 409, 419,
1987 421, 431, 433, 439, 443, 449, 457, 461,
1988 463, 467, 479, 487, 491, 499, 503, 509,
1989 521, 523, 541, 547, 557, 563, 569, 571,
1990 577, 587, 593, 599, 601, 607, 613, 617,
1991 619, 631, 641, 643, 647, 653, 659, 661,
1992 673, 677, 683, 691, 701, 709, 719, 727,
1993 733, 739, 743, 751, 757, 761, 769, 773,
1994 787, 797, 809, 811, 821, 823, 827, 829,
1995 839, 853, 857, 859, 863, 877, 881, 883,
1996 887, 907, 911, 919, 929, 937, 941, 947,
1997 953, 967, 971, 977, 983, 991, 997, -103
1998};
1999
2000/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002001 * Small divisors test (X must be positive)
2002 *
2003 * Return values:
2004 * 0: no small factor (possible prime, more tests needed)
2005 * 1: certain prime
2006 * POLARSSL_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2007 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002008 */
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002009static int mpi_check_small_factors( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002010{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002011 int ret = 0;
2012 size_t i;
2013 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002014
Paul Bakker5121ce52009-01-03 21:22:43 +00002015 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002016 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002017
2018 for( i = 0; small_prime[i] > 0; i++ )
2019 {
Paul Bakker5121ce52009-01-03 21:22:43 +00002020 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002021 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
2023 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
2024
2025 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002026 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002027 }
2028
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002029cleanup:
2030 return( ret );
2031}
2032
2033/*
2034 * Miller-Rabin pseudo-primality test (HAC 4.24)
2035 */
2036static int mpi_miller_rabin( const mpi *X,
2037 int (*f_rng)(void *, unsigned char *, size_t),
2038 void *p_rng )
2039{
Pascal Junodb99183d2015-03-11 16:49:45 +01002040 int ret, count;
2041 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002042 mpi W, R, T, A, RR;
2043
2044 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
2045 mpi_init( &RR );
2046
Paul Bakker5121ce52009-01-03 21:22:43 +00002047 /*
2048 * W = |X| - 1
2049 * R = W >> lsb( W )
2050 */
Paul Bakker5121ce52009-01-03 21:22:43 +00002051 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00002052 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00002053 MPI_CHK( mpi_copy( &R, &W ) );
2054 MPI_CHK( mpi_shift_r( &R, s ) );
2055
2056 i = mpi_msb( X );
2057 /*
2058 * HAC, table 4.4
2059 */
2060 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2061 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2062 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2063
2064 for( i = 0; i < n; i++ )
2065 {
2066 /*
2067 * pick a random A, 1 < A < |X| - 1
2068 */
Paul Bakker5121ce52009-01-03 21:22:43 +00002069
Pascal Junodb99183d2015-03-11 16:49:45 +01002070 count = 0;
2071 do {
2072 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
2073
2074 j = mpi_msb( &A );
2075 k = mpi_msb( &W );
2076 if (j > k) {
2077 MPI_CHK( mpi_shift_r( &A, j - k ) );
2078 }
2079
2080 if (count++ > 30) {
2081 return POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
2082 }
2083
2084 } while ( (mpi_cmp_mpi( &A, &W ) >= 0) ||
2085 (mpi_cmp_int( &A, 1 ) <= 0) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002086
2087 /*
2088 * A = A^R mod |X|
2089 */
2090 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
2091
2092 if( mpi_cmp_mpi( &A, &W ) == 0 ||
2093 mpi_cmp_int( &A, 1 ) == 0 )
2094 continue;
2095
2096 j = 1;
2097 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
2098 {
2099 /*
2100 * A = A * A mod |X|
2101 */
2102 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
2103 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
2104
2105 if( mpi_cmp_int( &A, 1 ) == 0 )
2106 break;
2107
2108 j++;
2109 }
2110
2111 /*
2112 * not prime if A != |X| - 1 or A == 1
2113 */
2114 if( mpi_cmp_mpi( &A, &W ) != 0 ||
2115 mpi_cmp_int( &A, 1 ) == 0 )
2116 {
Paul Bakker40e46942009-01-03 21:51:57 +00002117 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002118 break;
2119 }
2120 }
2121
2122cleanup:
Paul Bakker6c591fa2011-05-05 11:49:20 +00002123 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
2124 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002125
2126 return( ret );
2127}
2128
2129/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002130 * Pseudo-primality test: small factors, then Miller-Rabin
2131 */
Paul Bakker45f457d2013-11-25 14:26:52 +01002132int mpi_is_prime( mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002133 int (*f_rng)(void *, unsigned char *, size_t),
2134 void *p_rng )
2135{
2136 int ret;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002137 mpi XX;
2138
2139 XX.s = 1;
2140 XX.n = X->n;
2141 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002142
2143 if( mpi_cmp_int( &XX, 0 ) == 0 ||
2144 mpi_cmp_int( &XX, 1 ) == 0 )
2145 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
2146
2147 if( mpi_cmp_int( &XX, 2 ) == 0 )
2148 return( 0 );
2149
2150 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2151 {
2152 if( ret == 1 )
2153 return( 0 );
2154
2155 return( ret );
2156 }
2157
2158 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2159}
2160
2161/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002162 * Prime number generation
2163 */
Paul Bakker23986e52011-04-24 08:57:21 +00002164int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002165 int (*f_rng)(void *, unsigned char *, size_t),
2166 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002167{
Paul Bakker23986e52011-04-24 08:57:21 +00002168 int ret;
2169 size_t k, n;
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002170 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002171 mpi Y;
2172
Paul Bakkerfe3256e2011-11-25 12:11:43 +00002173 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00002174 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002175
Paul Bakker6c591fa2011-05-05 11:49:20 +00002176 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002177
2178 n = BITS_TO_LIMBS( nbits );
2179
Paul Bakker901c6562012-04-20 13:25:38 +00002180 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002181
2182 k = mpi_msb( X );
Pascal Junodb99183d2015-03-11 16:49:45 +01002183 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002184
Pascal Junodb99183d2015-03-11 16:49:45 +01002185 mpi_set_bit( X, nbits-1, 1 );
2186
2187 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002188
2189 if( dh_flag == 0 )
2190 {
2191 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
2192 {
Paul Bakker40e46942009-01-03 21:51:57 +00002193 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002194 goto cleanup;
2195
2196 MPI_CHK( mpi_add_int( X, X, 2 ) );
2197 }
2198 }
2199 else
2200 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002201 /*
2202 * An necessary condition for Y and X = 2Y + 1 to be prime
2203 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2204 * Make sure it is satisfied, while keeping X = 3 mod 4
2205 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002206
2207 X->p[0] |= 2;
2208
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002209 MPI_CHK( mpi_mod_int( &r, X, 3 ) );
2210 if( r == 0 )
2211 MPI_CHK( mpi_add_int( X, X, 8 ) );
2212 else if( r == 1 )
2213 MPI_CHK( mpi_add_int( X, X, 4 ) );
2214
2215 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2216 MPI_CHK( mpi_copy( &Y, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002217 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2218
2219 while( 1 )
2220 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002221 /*
2222 * First, check small factors for X and Y
2223 * before doing Miller-Rabin on any of them
2224 */
2225 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2226 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2227 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2228 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002229 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002230 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002231 }
2232
Paul Bakker40e46942009-01-03 21:51:57 +00002233 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002234 goto cleanup;
2235
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002236 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002237 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002238 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2239 * so up Y by 6 and X by 12.
2240 */
2241 MPI_CHK( mpi_add_int( X, X, 12 ) );
2242 MPI_CHK( mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002243 }
2244 }
2245
2246cleanup:
2247
Paul Bakker6c591fa2011-05-05 11:49:20 +00002248 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002249
2250 return( ret );
2251}
2252
Manuel Pégourié-Gonnarddf0142b2013-08-22 18:29:07 +02002253#endif /* POLARSSL_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002254
Paul Bakker40e46942009-01-03 21:51:57 +00002255#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002256
Paul Bakker23986e52011-04-24 08:57:21 +00002257#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002258
2259static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2260{
2261 { 693, 609, 21 },
2262 { 1764, 868, 28 },
2263 { 768454923, 542167814, 1 }
2264};
2265
Paul Bakker5121ce52009-01-03 21:22:43 +00002266/*
2267 * Checkup routine
2268 */
2269int mpi_self_test( int verbose )
2270{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002271 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002272 mpi A, E, N, X, Y, U, V;
2273
Paul Bakker6c591fa2011-05-05 11:49:20 +00002274 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2275 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002276
2277 MPI_CHK( mpi_read_string( &A, 16,
2278 "EFE021C2645FD1DC586E69184AF4A31E" \
2279 "D5F53E93B5F123FA41680867BA110131" \
2280 "944FE7952E2517337780CB0DB80E61AA" \
2281 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2282
2283 MPI_CHK( mpi_read_string( &E, 16,
2284 "B2E7EFD37075B9F03FF989C7C5051C20" \
2285 "34D2A323810251127E7BF8625A4F49A5" \
2286 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2287 "5B5C25763222FEFCCFC38B832366C29E" ) );
2288
2289 MPI_CHK( mpi_read_string( &N, 16,
2290 "0066A198186C18C10B2F5ED9B522752A" \
2291 "9830B69916E535C8F047518A889A43A5" \
2292 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2293
2294 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2295
2296 MPI_CHK( mpi_read_string( &U, 16,
2297 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2298 "9E857EA95A03512E2BAE7391688D264A" \
2299 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2300 "8001B72E848A38CAE1C65F78E56ABDEF" \
2301 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2302 "ECF677152EF804370C1A305CAF3B5BF1" \
2303 "30879B56C61DE584A0F53A2447A51E" ) );
2304
2305 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002306 polarssl_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002307
2308 if( mpi_cmp_mpi( &X, &U ) != 0 )
2309 {
2310 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002311 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002312
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002313 ret = 1;
2314 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002315 }
2316
2317 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002318 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002319
2320 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2321
2322 MPI_CHK( mpi_read_string( &U, 16,
2323 "256567336059E52CAE22925474705F39A94" ) );
2324
2325 MPI_CHK( mpi_read_string( &V, 16,
2326 "6613F26162223DF488E9CD48CC132C7A" \
2327 "0AC93C701B001B092E4E5B9F73BCD27B" \
2328 "9EE50D0657C77F374E903CDFA4C642" ) );
2329
2330 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002331 polarssl_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002332
2333 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2334 mpi_cmp_mpi( &Y, &V ) != 0 )
2335 {
2336 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002337 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002338
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002339 ret = 1;
2340 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002341 }
2342
2343 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002344 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002345
2346 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2347
2348 MPI_CHK( mpi_read_string( &U, 16,
2349 "36E139AEA55215609D2816998ED020BB" \
2350 "BD96C37890F65171D948E9BC7CBAA4D9" \
2351 "325D24D6A3C12710F10A09FA08AB87" ) );
2352
2353 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002354 polarssl_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002355
2356 if( mpi_cmp_mpi( &X, &U ) != 0 )
2357 {
2358 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002359 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002361 ret = 1;
2362 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002363 }
2364
2365 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002366 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002367
2368 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2369
2370 MPI_CHK( mpi_read_string( &U, 16,
2371 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2372 "C3DBA76456363A10869622EAC2DD84EC" \
2373 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2374
2375 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002376 polarssl_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002377
2378 if( mpi_cmp_mpi( &X, &U ) != 0 )
2379 {
2380 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002381 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002382
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002383 ret = 1;
2384 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002385 }
2386
2387 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002388 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002389
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002390 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002391 polarssl_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002392
Paul Bakker66d5d072014-06-17 16:39:18 +02002393 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002394 {
2395 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002396 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002397
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002398 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002399
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002400 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2401 {
2402 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002403 polarssl_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002404
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002405 ret = 1;
2406 goto cleanup;
2407 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002408 }
2409
2410 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002411 polarssl_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002412
Paul Bakker5121ce52009-01-03 21:22:43 +00002413cleanup:
2414
2415 if( ret != 0 && verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002416 polarssl_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002417
Paul Bakker6c591fa2011-05-05 11:49:20 +00002418 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2419 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002420
2421 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002422 polarssl_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002423
2424 return( ret );
2425}
2426
Paul Bakker9af723c2014-05-01 13:03:14 +02002427#endif /* POLARSSL_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002428
Paul Bakker9af723c2014-05-01 13:03:14 +02002429#endif /* POLARSSL_BIGNUM_C */