blob: 73ea453605b0080458791d63417ef9781d0b7ed6 [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 {
Janos Follath87f14942015-10-25 10:58:03 +0100896 const mpi *T;
897
898 if( B == A)
899 return mpi_shift_l( X, 1 );
900
901 T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000902 }
903
904 if( X != A )
905 MPI_CHK( mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200906
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000907 /*
908 * X should always be positive as a result of unsigned additions.
909 */
910 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000911
Paul Bakker23986e52011-04-24 08:57:21 +0000912 for( j = B->n; j > 0; j-- )
913 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000914 break;
915
Paul Bakker23986e52011-04-24 08:57:21 +0000916 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000917
918 o = B->p; p = X->p; c = 0;
919
Paul Bakker23986e52011-04-24 08:57:21 +0000920 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000921 {
922 *p += c; c = ( *p < c );
923 *p += *o; c += ( *p < *o );
924 }
925
926 while( c != 0 )
927 {
928 if( i >= X->n )
929 {
930 MPI_CHK( mpi_grow( X, i + 1 ) );
931 p = X->p + i;
932 }
933
Paul Bakker2d319fd2012-09-16 21:34:26 +0000934 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000935 }
936
937cleanup:
938
939 return( ret );
940}
941
942/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100943 * Helper for mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000944 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000945static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000946{
Paul Bakker23986e52011-04-24 08:57:21 +0000947 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000948 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000949
950 for( i = c = 0; i < n; i++, s++, d++ )
951 {
952 z = ( *d < c ); *d -= c;
953 c = ( *d < *s ) + z; *d -= *s;
954 }
955
956 while( c != 0 )
957 {
958 z = ( *d < c ); *d -= c;
959 c = z; i++; d++;
960 }
961}
962
963/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100964 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000965 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000966int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000967{
968 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000969 int ret;
970 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000971
972 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000973 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000974
Paul Bakker6c591fa2011-05-05 11:49:20 +0000975 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000976
977 if( X == B )
978 {
979 MPI_CHK( mpi_copy( &TB, B ) );
980 B = &TB;
981 }
982
983 if( X != A )
984 MPI_CHK( mpi_copy( X, A ) );
985
Paul Bakker1ef7a532009-06-20 10:50:55 +0000986 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100987 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000988 */
989 X->s = 1;
990
Paul Bakker5121ce52009-01-03 21:22:43 +0000991 ret = 0;
992
Paul Bakker23986e52011-04-24 08:57:21 +0000993 for( n = B->n; n > 0; n-- )
994 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000995 break;
996
Paul Bakker23986e52011-04-24 08:57:21 +0000997 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000998
999cleanup:
1000
Paul Bakker6c591fa2011-05-05 11:49:20 +00001001 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001002
1003 return( ret );
1004}
1005
1006/*
1007 * Signed addition: X = A + B
1008 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001009int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001010{
1011 int ret, s = A->s;
1012
1013 if( A->s * B->s < 0 )
1014 {
1015 if( mpi_cmp_abs( A, B ) >= 0 )
1016 {
1017 MPI_CHK( mpi_sub_abs( X, A, B ) );
1018 X->s = s;
1019 }
1020 else
1021 {
1022 MPI_CHK( mpi_sub_abs( X, B, A ) );
1023 X->s = -s;
1024 }
1025 }
1026 else
1027 {
1028 MPI_CHK( mpi_add_abs( X, A, B ) );
1029 X->s = s;
1030 }
1031
1032cleanup:
1033
1034 return( ret );
1035}
1036
1037/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001038 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001039 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001040int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001041{
1042 int ret, s = A->s;
1043
1044 if( A->s * B->s > 0 )
1045 {
1046 if( mpi_cmp_abs( A, B ) >= 0 )
1047 {
1048 MPI_CHK( mpi_sub_abs( X, A, B ) );
1049 X->s = s;
1050 }
1051 else
1052 {
1053 MPI_CHK( mpi_sub_abs( X, B, A ) );
1054 X->s = -s;
1055 }
1056 }
1057 else
1058 {
1059 MPI_CHK( mpi_add_abs( X, A, B ) );
1060 X->s = s;
1061 }
1062
1063cleanup:
1064
1065 return( ret );
1066}
1067
1068/*
1069 * Signed addition: X = A + b
1070 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001071int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001072{
1073 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001074 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001075
1076 p[0] = ( b < 0 ) ? -b : b;
1077 _B.s = ( b < 0 ) ? -1 : 1;
1078 _B.n = 1;
1079 _B.p = p;
1080
1081 return( mpi_add_mpi( X, A, &_B ) );
1082}
1083
1084/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001085 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001086 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001087int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001088{
1089 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001090 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001091
1092 p[0] = ( b < 0 ) ? -b : b;
1093 _B.s = ( b < 0 ) ? -1 : 1;
1094 _B.n = 1;
1095 _B.p = p;
1096
1097 return( mpi_sub_mpi( X, A, &_B ) );
1098}
1099
1100/*
1101 * Helper for mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001102 */
1103static
1104#if defined(__APPLE__) && defined(__arm__)
1105/*
1106 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1107 * appears to need this to prevent bad ARM code generation at -O3.
1108 */
1109__attribute__ ((noinline))
1110#endif
1111void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001112{
Paul Bakkera755ca12011-04-24 09:11:17 +00001113 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001114
1115#if defined(MULADDC_HUIT)
1116 for( ; i >= 8; i -= 8 )
1117 {
1118 MULADDC_INIT
1119 MULADDC_HUIT
1120 MULADDC_STOP
1121 }
1122
1123 for( ; i > 0; i-- )
1124 {
1125 MULADDC_INIT
1126 MULADDC_CORE
1127 MULADDC_STOP
1128 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001129#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001130 for( ; i >= 16; i -= 16 )
1131 {
1132 MULADDC_INIT
1133 MULADDC_CORE MULADDC_CORE
1134 MULADDC_CORE MULADDC_CORE
1135 MULADDC_CORE MULADDC_CORE
1136 MULADDC_CORE MULADDC_CORE
1137
1138 MULADDC_CORE MULADDC_CORE
1139 MULADDC_CORE MULADDC_CORE
1140 MULADDC_CORE MULADDC_CORE
1141 MULADDC_CORE MULADDC_CORE
1142 MULADDC_STOP
1143 }
1144
1145 for( ; i >= 8; i -= 8 )
1146 {
1147 MULADDC_INIT
1148 MULADDC_CORE MULADDC_CORE
1149 MULADDC_CORE MULADDC_CORE
1150
1151 MULADDC_CORE MULADDC_CORE
1152 MULADDC_CORE MULADDC_CORE
1153 MULADDC_STOP
1154 }
1155
1156 for( ; i > 0; i-- )
1157 {
1158 MULADDC_INIT
1159 MULADDC_CORE
1160 MULADDC_STOP
1161 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001162#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001163
1164 t++;
1165
1166 do {
1167 *d += c; c = ( *d < c ); d++;
1168 }
1169 while( c != 0 );
1170}
1171
1172/*
1173 * Baseline multiplication: X = A * B (HAC 14.12)
1174 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001175int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001176{
Paul Bakker23986e52011-04-24 08:57:21 +00001177 int ret;
1178 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001179 mpi TA, TB;
1180
Paul Bakker6c591fa2011-05-05 11:49:20 +00001181 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001182
1183 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1184 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1185
Paul Bakker23986e52011-04-24 08:57:21 +00001186 for( i = A->n; i > 0; i-- )
1187 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001188 break;
1189
Paul Bakker23986e52011-04-24 08:57:21 +00001190 for( j = B->n; j > 0; j-- )
1191 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001192 break;
1193
Paul Bakker23986e52011-04-24 08:57:21 +00001194 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001195 MPI_CHK( mpi_lset( X, 0 ) );
1196
Paul Bakker23986e52011-04-24 08:57:21 +00001197 for( i++; j > 0; j-- )
1198 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001199
1200 X->s = A->s * B->s;
1201
1202cleanup:
1203
Paul Bakker6c591fa2011-05-05 11:49:20 +00001204 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001205
1206 return( ret );
1207}
1208
1209/*
1210 * Baseline multiplication: X = A * b
1211 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001212int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001213{
1214 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001215 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001216
1217 _B.s = 1;
1218 _B.n = 1;
1219 _B.p = p;
1220 p[0] = b;
1221
1222 return( mpi_mul_mpi( X, A, &_B ) );
1223}
1224
1225/*
Simon Butcher14400c82016-01-02 00:08:13 +00001226 * Unsigned integer divide - double t_uint, dividend, u1/u0, and t_uint
1227 * divisor, d
Simon Butchere4ed3472015-12-22 15:26:57 +00001228 */
Simon Butcher14400c82016-01-02 00:08:13 +00001229static t_uint int_div_int( t_uint u1, t_uint u0, t_uint d, t_uint *r )
Simon Butchere4ed3472015-12-22 15:26:57 +00001230{
1231#if defined(POLARSSL_HAVE_UDBL)
1232 t_udbl dividend, quotient;
Simon Butcher14400c82016-01-02 00:08:13 +00001233#else
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001234 const t_uint radix = (t_uint) 1 << biH;
1235 const t_uint uint_halfword_mask = ( (t_uint) 1 << biH ) - 1;
Simon Butcher14400c82016-01-02 00:08:13 +00001236 t_uint d0, d1, q0, q1, rAX, r0, quotient;
1237 t_uint u0_msw, u0_lsw;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001238 size_t s;
Simon Butchere4ed3472015-12-22 15:26:57 +00001239#endif
1240
1241 /*
1242 * Check for overflow
1243 */
Simon Butcher14400c82016-01-02 00:08:13 +00001244 if( 0 == d || u1 >= d )
Simon Butchere4ed3472015-12-22 15:26:57 +00001245 {
Simon Butcher14400c82016-01-02 00:08:13 +00001246 if ( r != NULL ) *r = ~0;
Simon Butchere4ed3472015-12-22 15:26:57 +00001247
Simon Butcher14400c82016-01-02 00:08:13 +00001248 return ( ~0 );
Simon Butchere4ed3472015-12-22 15:26:57 +00001249 }
1250
1251#if defined(POLARSSL_HAVE_UDBL)
1252 dividend = (t_udbl) u1 << biL;
1253 dividend |= (t_udbl) u0;
1254 quotient = dividend / d;
1255 if( quotient > ( (t_udbl) 1 << biL ) - 1 )
1256 quotient = ( (t_udbl) 1 << biL ) - 1;
1257
1258 if( r != NULL )
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001259 *r = (t_uint)( dividend - (quotient * d ) );
Simon Butchere4ed3472015-12-22 15:26:57 +00001260
1261 return (t_uint) quotient;
1262#else
Simon Butchere4ed3472015-12-22 15:26:57 +00001263
1264 /*
1265 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1266 * Vol. 2 - Seminumerical Algorithms, Knuth
1267 */
1268
1269 /*
1270 * Normalize the divisor, d, and dividend, u0, u1
1271 */
1272 s = int_clz( d );
1273 d = d << s;
1274
1275 u1 = u1 << s;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001276 u1 |= ( u0 >> ( biL - s ) ) & ( -(t_sint)s >> ( biL - 1 ) );
Simon Butchere4ed3472015-12-22 15:26:57 +00001277 u0 = u0 << s;
1278
1279 d1 = d >> biH;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001280 d0 = d & uint_halfword_mask;
Simon Butchere4ed3472015-12-22 15:26:57 +00001281
1282 u0_msw = u0 >> biH;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001283 u0_lsw = u0 & uint_halfword_mask;
Simon Butchere4ed3472015-12-22 15:26:57 +00001284
1285 /*
1286 * Find the first quotient and remainder
1287 */
1288 q1 = u1 / d1;
1289 r0 = u1 - d1 * q1;
1290
1291 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1292 {
1293 q1 -= 1;
1294 r0 += d1;
1295
1296 if ( r0 >= radix ) break;
1297 }
1298
Simon Butcher14400c82016-01-02 00:08:13 +00001299 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butchere4ed3472015-12-22 15:26:57 +00001300 q0 = rAX / d1;
1301 r0 = rAX - q0 * d1;
1302
1303 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1304 {
1305 q0 -= 1;
1306 r0 += d1;
1307
1308 if ( r0 >= radix ) break;
1309 }
1310
1311 if (r != NULL)
Simon Butcher14400c82016-01-02 00:08:13 +00001312 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butchere4ed3472015-12-22 15:26:57 +00001313
1314 quotient = q1 * radix + q0;
1315
1316 return quotient;
1317#endif
1318}
1319
1320/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001321 * Division by mpi: A = Q * B + R (HAC 14.20)
1322 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001323int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001324{
Paul Bakker23986e52011-04-24 08:57:21 +00001325 int ret;
1326 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001327 mpi X, Y, Z, T1, T2;
1328
1329 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001330 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001331
Paul Bakker6c591fa2011-05-05 11:49:20 +00001332 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1333 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001334
1335 if( mpi_cmp_abs( A, B ) < 0 )
1336 {
1337 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1338 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1339 return( 0 );
1340 }
1341
1342 MPI_CHK( mpi_copy( &X, A ) );
1343 MPI_CHK( mpi_copy( &Y, B ) );
1344 X.s = Y.s = 1;
1345
1346 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1347 MPI_CHK( mpi_lset( &Z, 0 ) );
1348 MPI_CHK( mpi_grow( &T1, 2 ) );
1349 MPI_CHK( mpi_grow( &T2, 3 ) );
1350
1351 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001352 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001353 {
1354 k = biL - 1 - k;
1355 MPI_CHK( mpi_shift_l( &X, k ) );
1356 MPI_CHK( mpi_shift_l( &Y, k ) );
1357 }
1358 else k = 0;
1359
1360 n = X.n - 1;
1361 t = Y.n - 1;
Paul Bakker66d5d072014-06-17 16:39:18 +02001362 MPI_CHK( mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001363
1364 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1365 {
1366 Z.p[n - t]++;
Paul Bakker6ea1a952013-12-31 11:16:03 +01001367 MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001368 }
Paul Bakker66d5d072014-06-17 16:39:18 +02001369 MPI_CHK( mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001370
1371 for( i = n; i > t ; i-- )
1372 {
1373 if( X.p[i] >= Y.p[t] )
1374 Z.p[i - t - 1] = ~0;
1375 else
1376 {
Simon Butchere4ed3472015-12-22 15:26:57 +00001377 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 +00001378 }
1379
1380 Z.p[i - t - 1]++;
1381 do
1382 {
1383 Z.p[i - t - 1]--;
1384
1385 MPI_CHK( mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001386 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001387 T1.p[1] = Y.p[t];
1388 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1389
1390 MPI_CHK( mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001391 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1392 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001393 T2.p[2] = X.p[i];
1394 }
1395 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1396
1397 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001398 MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001399 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1400
1401 if( mpi_cmp_int( &X, 0 ) < 0 )
1402 {
1403 MPI_CHK( mpi_copy( &T1, &Y ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001404 MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001405 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1406 Z.p[i - t - 1]--;
1407 }
1408 }
1409
1410 if( Q != NULL )
1411 {
Paul Bakker6ea1a952013-12-31 11:16:03 +01001412 MPI_CHK( mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001413 Q->s = A->s * B->s;
1414 }
1415
1416 if( R != NULL )
1417 {
Paul Bakker6ea1a952013-12-31 11:16:03 +01001418 MPI_CHK( mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001419 X.s = A->s;
Paul Bakker6ea1a952013-12-31 11:16:03 +01001420 MPI_CHK( mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001421
Paul Bakker5121ce52009-01-03 21:22:43 +00001422 if( mpi_cmp_int( R, 0 ) == 0 )
1423 R->s = 1;
1424 }
1425
1426cleanup:
1427
Paul Bakker6c591fa2011-05-05 11:49:20 +00001428 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1429 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001430
1431 return( ret );
1432}
1433
1434/*
1435 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001436 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001437int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001438{
1439 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001440 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001441
1442 p[0] = ( b < 0 ) ? -b : b;
1443 _B.s = ( b < 0 ) ? -1 : 1;
1444 _B.n = 1;
1445 _B.p = p;
1446
1447 return( mpi_div_mpi( Q, R, A, &_B ) );
1448}
1449
1450/*
1451 * Modulo: R = A mod B
1452 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001453int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001454{
1455 int ret;
1456
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001457 if( mpi_cmp_int( B, 0 ) < 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001458 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001459
Paul Bakker5121ce52009-01-03 21:22:43 +00001460 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1461
1462 while( mpi_cmp_int( R, 0 ) < 0 )
1463 MPI_CHK( mpi_add_mpi( R, R, B ) );
1464
1465 while( mpi_cmp_mpi( R, B ) >= 0 )
1466 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1467
1468cleanup:
1469
1470 return( ret );
1471}
1472
1473/*
1474 * Modulo: r = A mod b
1475 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001476int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001477{
Paul Bakker23986e52011-04-24 08:57:21 +00001478 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001479 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001480
1481 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001482 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001483
1484 if( b < 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001485 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001486
1487 /*
1488 * handle trivial cases
1489 */
1490 if( b == 1 )
1491 {
1492 *r = 0;
1493 return( 0 );
1494 }
1495
1496 if( b == 2 )
1497 {
1498 *r = A->p[0] & 1;
1499 return( 0 );
1500 }
1501
1502 /*
1503 * general case
1504 */
Paul Bakker23986e52011-04-24 08:57:21 +00001505 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001506 {
Paul Bakker23986e52011-04-24 08:57:21 +00001507 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001508 y = ( y << biH ) | ( x >> biH );
1509 z = y / b;
1510 y -= z * b;
1511
1512 x <<= biH;
1513 y = ( y << biH ) | ( x >> biH );
1514 z = y / b;
1515 y -= z * b;
1516 }
1517
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001518 /*
1519 * If A is negative, then the current y represents a negative value.
1520 * Flipping it to the positive side.
1521 */
1522 if( A->s < 0 && y != 0 )
1523 y = b - y;
1524
Paul Bakker5121ce52009-01-03 21:22:43 +00001525 *r = y;
1526
1527 return( 0 );
1528}
1529
1530/*
1531 * Fast Montgomery initialization (thanks to Tom St Denis)
1532 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001533static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001534{
Paul Bakkera755ca12011-04-24 09:11:17 +00001535 t_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001536 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001537
1538 x = m0;
1539 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001540
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001541 for( i = biL; i >= 8; i /= 2 )
1542 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001543
1544 *mm = ~x + 1;
1545}
1546
1547/*
1548 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1549 */
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02001550static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm,
1551 const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001552{
Paul Bakker23986e52011-04-24 08:57:21 +00001553 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001554 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001555
1556 memset( T->p, 0, T->n * ciL );
1557
1558 d = T->p;
1559 n = N->n;
1560 m = ( B->n < n ) ? B->n : n;
1561
1562 for( i = 0; i < n; i++ )
1563 {
1564 /*
1565 * T = (T + u0*B + u1*N) / 2^biL
1566 */
1567 u0 = A->p[i];
1568 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1569
1570 mpi_mul_hlp( m, B->p, d, u0 );
1571 mpi_mul_hlp( n, N->p, d, u1 );
1572
1573 *d++ = u0; d[n + 1] = 0;
1574 }
1575
Paul Bakker66d5d072014-06-17 16:39:18 +02001576 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001577
1578 if( mpi_cmp_abs( A, N ) >= 0 )
1579 mpi_sub_hlp( n, N->p, A->p );
1580 else
1581 /* prevent timing attacks */
1582 mpi_sub_hlp( n, A->p, T->p );
1583}
1584
1585/*
1586 * Montgomery reduction: A = A * R^-1 mod N
1587 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001588static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001589{
Paul Bakkera755ca12011-04-24 09:11:17 +00001590 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001591 mpi U;
1592
Paul Bakker8ddb6452013-02-27 14:56:33 +01001593 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001594 U.p = &z;
1595
1596 mpi_montmul( A, &U, N, mm, T );
1597}
1598
1599/*
1600 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1601 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001602int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001603{
Paul Bakker23986e52011-04-24 08:57:21 +00001604 int ret;
1605 size_t wbits, wsize, one = 1;
1606 size_t i, j, nblimbs;
1607 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001608 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001609 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1610 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001611
1612 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001613 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001614
Paul Bakkerf6198c12012-05-16 08:02:29 +00001615 if( mpi_cmp_int( E, 0 ) < 0 )
1616 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1617
1618 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001619 * Init temps and window size
1620 */
1621 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001622 mpi_init( &RR ); mpi_init( &T );
Manuel Pégourié-Gonnardfd6a1912014-01-18 19:05:23 +01001623 mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001624 memset( W, 0, sizeof( W ) );
1625
1626 i = mpi_msb( E );
1627
1628 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1629 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1630
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001631 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1632 wsize = POLARSSL_MPI_WINDOW_SIZE;
1633
Paul Bakker5121ce52009-01-03 21:22:43 +00001634 j = N->n + 1;
1635 MPI_CHK( mpi_grow( X, j ) );
1636 MPI_CHK( mpi_grow( &W[1], j ) );
1637 MPI_CHK( mpi_grow( &T, j * 2 ) );
1638
1639 /*
Paul Bakker50546922012-05-19 08:40:49 +00001640 * Compensate for negative A (and correct at the end)
1641 */
1642 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001643 if( neg )
1644 {
1645 MPI_CHK( mpi_copy( &Apos, A ) );
1646 Apos.s = 1;
1647 A = &Apos;
1648 }
1649
1650 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001651 * If 1st call, pre-compute R^2 mod N
1652 */
1653 if( _RR == NULL || _RR->p == NULL )
1654 {
1655 MPI_CHK( mpi_lset( &RR, 1 ) );
1656 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1657 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1658
1659 if( _RR != NULL )
1660 memcpy( _RR, &RR, sizeof( mpi ) );
1661 }
1662 else
1663 memcpy( &RR, _RR, sizeof( mpi ) );
1664
1665 /*
1666 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1667 */
1668 if( mpi_cmp_mpi( A, N ) >= 0 )
Paul Bakkerc2024f42014-01-23 20:38:35 +01001669 MPI_CHK( mpi_mod_mpi( &W[1], A, N ) );
1670 else
1671 MPI_CHK( mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001672
1673 mpi_montmul( &W[1], &RR, N, mm, &T );
1674
1675 /*
1676 * X = R^2 * R^-1 mod N = R mod N
1677 */
1678 MPI_CHK( mpi_copy( X, &RR ) );
1679 mpi_montred( X, N, mm, &T );
1680
1681 if( wsize > 1 )
1682 {
1683 /*
1684 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1685 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001686 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001687
1688 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1689 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1690
1691 for( i = 0; i < wsize - 1; i++ )
1692 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001693
Paul Bakker5121ce52009-01-03 21:22:43 +00001694 /*
1695 * W[i] = W[i - 1] * W[1]
1696 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001697 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001698 {
1699 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1700 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1701
1702 mpi_montmul( &W[i], &W[1], N, mm, &T );
1703 }
1704 }
1705
1706 nblimbs = E->n;
1707 bufsize = 0;
1708 nbits = 0;
1709 wbits = 0;
1710 state = 0;
1711
1712 while( 1 )
1713 {
1714 if( bufsize == 0 )
1715 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001716 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001717 break;
1718
Paul Bakker0d7702c2013-10-29 16:18:35 +01001719 nblimbs--;
1720
Paul Bakkera755ca12011-04-24 09:11:17 +00001721 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001722 }
1723
1724 bufsize--;
1725
1726 ei = (E->p[nblimbs] >> bufsize) & 1;
1727
1728 /*
1729 * skip leading 0s
1730 */
1731 if( ei == 0 && state == 0 )
1732 continue;
1733
1734 if( ei == 0 && state == 1 )
1735 {
1736 /*
1737 * out of window, square X
1738 */
1739 mpi_montmul( X, X, N, mm, &T );
1740 continue;
1741 }
1742
1743 /*
1744 * add ei to current window
1745 */
1746 state = 2;
1747
1748 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001749 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001750
1751 if( nbits == wsize )
1752 {
1753 /*
1754 * X = X^wsize R^-1 mod N
1755 */
1756 for( i = 0; i < wsize; i++ )
1757 mpi_montmul( X, X, N, mm, &T );
1758
1759 /*
1760 * X = X * W[wbits] R^-1 mod N
1761 */
1762 mpi_montmul( X, &W[wbits], N, mm, &T );
1763
1764 state--;
1765 nbits = 0;
1766 wbits = 0;
1767 }
1768 }
1769
1770 /*
1771 * process the remaining bits
1772 */
1773 for( i = 0; i < nbits; i++ )
1774 {
1775 mpi_montmul( X, X, N, mm, &T );
1776
1777 wbits <<= 1;
1778
Paul Bakker66d5d072014-06-17 16:39:18 +02001779 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001780 mpi_montmul( X, &W[1], N, mm, &T );
1781 }
1782
1783 /*
1784 * X = A^E * R * R^-1 mod N = A^E mod N
1785 */
1786 mpi_montred( X, N, mm, &T );
1787
Paul Bakkerf6198c12012-05-16 08:02:29 +00001788 if( neg )
1789 {
1790 X->s = -1;
Paul Bakkerc2024f42014-01-23 20:38:35 +01001791 MPI_CHK( mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001792 }
1793
Paul Bakker5121ce52009-01-03 21:22:43 +00001794cleanup:
1795
Paul Bakker66d5d072014-06-17 16:39:18 +02001796 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001797 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001798
Paul Bakkerf6198c12012-05-16 08:02:29 +00001799 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001800
Paul Bakker75a28602014-03-31 12:08:17 +02001801 if( _RR == NULL || _RR->p == NULL )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001802 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001803
1804 return( ret );
1805}
1806
Paul Bakker5121ce52009-01-03 21:22:43 +00001807/*
1808 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1809 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001810int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001811{
Paul Bakker23986e52011-04-24 08:57:21 +00001812 int ret;
1813 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001814 mpi TG, TA, TB;
1815
Paul Bakker6c591fa2011-05-05 11:49:20 +00001816 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001817
Paul Bakker5121ce52009-01-03 21:22:43 +00001818 MPI_CHK( mpi_copy( &TA, A ) );
1819 MPI_CHK( mpi_copy( &TB, B ) );
1820
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001821 lz = mpi_lsb( &TA );
1822 lzt = mpi_lsb( &TB );
1823
Paul Bakker66d5d072014-06-17 16:39:18 +02001824 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001825 lz = lzt;
1826
1827 MPI_CHK( mpi_shift_r( &TA, lz ) );
1828 MPI_CHK( mpi_shift_r( &TB, lz ) );
1829
Paul Bakker5121ce52009-01-03 21:22:43 +00001830 TA.s = TB.s = 1;
1831
1832 while( mpi_cmp_int( &TA, 0 ) != 0 )
1833 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001834 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1835 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001836
1837 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1838 {
1839 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1840 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1841 }
1842 else
1843 {
1844 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1845 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1846 }
1847 }
1848
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001849 MPI_CHK( mpi_shift_l( &TB, lz ) );
1850 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001851
1852cleanup:
1853
Paul Bakker6c591fa2011-05-05 11:49:20 +00001854 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001855
1856 return( ret );
1857}
1858
Paul Bakker33dc46b2014-04-30 16:11:39 +02001859/*
1860 * Fill X with size bytes of random.
1861 *
1862 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001863 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001864 * deterministic, eg for tests).
1865 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001866int mpi_fill_random( mpi *X, size_t size,
1867 int (*f_rng)(void *, unsigned char *, size_t),
1868 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001869{
Paul Bakker23986e52011-04-24 08:57:21 +00001870 int ret;
Paul Bakker33dc46b2014-04-30 16:11:39 +02001871 unsigned char buf[POLARSSL_MPI_MAX_SIZE];
1872
1873 if( size > POLARSSL_MPI_MAX_SIZE )
1874 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001875
Paul Bakker33dc46b2014-04-30 16:11:39 +02001876 MPI_CHK( f_rng( p_rng, buf, size ) );
1877 MPI_CHK( mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001878
1879cleanup:
1880 return( ret );
1881}
1882
Paul Bakker5121ce52009-01-03 21:22:43 +00001883/*
1884 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1885 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001886int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001887{
1888 int ret;
1889 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1890
1891 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001892 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001893
Paul Bakker6c591fa2011-05-05 11:49:20 +00001894 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1895 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1896 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001897
1898 MPI_CHK( mpi_gcd( &G, A, N ) );
1899
1900 if( mpi_cmp_int( &G, 1 ) != 0 )
1901 {
Paul Bakker40e46942009-01-03 21:51:57 +00001902 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001903 goto cleanup;
1904 }
1905
1906 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1907 MPI_CHK( mpi_copy( &TU, &TA ) );
1908 MPI_CHK( mpi_copy( &TB, N ) );
1909 MPI_CHK( mpi_copy( &TV, N ) );
1910
1911 MPI_CHK( mpi_lset( &U1, 1 ) );
1912 MPI_CHK( mpi_lset( &U2, 0 ) );
1913 MPI_CHK( mpi_lset( &V1, 0 ) );
1914 MPI_CHK( mpi_lset( &V2, 1 ) );
1915
1916 do
1917 {
1918 while( ( TU.p[0] & 1 ) == 0 )
1919 {
1920 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1921
1922 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1923 {
1924 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1925 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1926 }
1927
1928 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1929 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1930 }
1931
1932 while( ( TV.p[0] & 1 ) == 0 )
1933 {
1934 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1935
1936 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1937 {
1938 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1939 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1940 }
1941
1942 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1943 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1944 }
1945
1946 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1947 {
1948 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1949 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1950 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1951 }
1952 else
1953 {
1954 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1955 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1956 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1957 }
1958 }
1959 while( mpi_cmp_int( &TU, 0 ) != 0 );
1960
1961 while( mpi_cmp_int( &V1, 0 ) < 0 )
1962 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1963
1964 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1965 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1966
1967 MPI_CHK( mpi_copy( X, &V1 ) );
1968
1969cleanup:
1970
Paul Bakker6c591fa2011-05-05 11:49:20 +00001971 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1972 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1973 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001974
1975 return( ret );
1976}
1977
Paul Bakkerd9374b02012-11-02 11:02:58 +00001978#if defined(POLARSSL_GENPRIME)
1979
Paul Bakker5121ce52009-01-03 21:22:43 +00001980static const int small_prime[] =
1981{
1982 3, 5, 7, 11, 13, 17, 19, 23,
1983 29, 31, 37, 41, 43, 47, 53, 59,
1984 61, 67, 71, 73, 79, 83, 89, 97,
1985 101, 103, 107, 109, 113, 127, 131, 137,
1986 139, 149, 151, 157, 163, 167, 173, 179,
1987 181, 191, 193, 197, 199, 211, 223, 227,
1988 229, 233, 239, 241, 251, 257, 263, 269,
1989 271, 277, 281, 283, 293, 307, 311, 313,
1990 317, 331, 337, 347, 349, 353, 359, 367,
1991 373, 379, 383, 389, 397, 401, 409, 419,
1992 421, 431, 433, 439, 443, 449, 457, 461,
1993 463, 467, 479, 487, 491, 499, 503, 509,
1994 521, 523, 541, 547, 557, 563, 569, 571,
1995 577, 587, 593, 599, 601, 607, 613, 617,
1996 619, 631, 641, 643, 647, 653, 659, 661,
1997 673, 677, 683, 691, 701, 709, 719, 727,
1998 733, 739, 743, 751, 757, 761, 769, 773,
1999 787, 797, 809, 811, 821, 823, 827, 829,
2000 839, 853, 857, 859, 863, 877, 881, 883,
2001 887, 907, 911, 919, 929, 937, 941, 947,
2002 953, 967, 971, 977, 983, 991, 997, -103
2003};
2004
2005/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002006 * Small divisors test (X must be positive)
2007 *
2008 * Return values:
2009 * 0: no small factor (possible prime, more tests needed)
2010 * 1: certain prime
2011 * POLARSSL_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2012 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002013 */
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002014static int mpi_check_small_factors( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002015{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002016 int ret = 0;
2017 size_t i;
2018 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002019
Paul Bakker5121ce52009-01-03 21:22:43 +00002020 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002021 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
2023 for( i = 0; small_prime[i] > 0; i++ )
2024 {
Paul Bakker5121ce52009-01-03 21:22:43 +00002025 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002026 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002027
2028 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
2029
2030 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002031 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002032 }
2033
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002034cleanup:
2035 return( ret );
2036}
2037
2038/*
2039 * Miller-Rabin pseudo-primality test (HAC 4.24)
2040 */
2041static int mpi_miller_rabin( const mpi *X,
2042 int (*f_rng)(void *, unsigned char *, size_t),
2043 void *p_rng )
2044{
Pascal Junodb99183d2015-03-11 16:49:45 +01002045 int ret, count;
2046 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002047 mpi W, R, T, A, RR;
2048
2049 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
2050 mpi_init( &RR );
2051
Paul Bakker5121ce52009-01-03 21:22:43 +00002052 /*
2053 * W = |X| - 1
2054 * R = W >> lsb( W )
2055 */
Paul Bakker5121ce52009-01-03 21:22:43 +00002056 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00002057 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00002058 MPI_CHK( mpi_copy( &R, &W ) );
2059 MPI_CHK( mpi_shift_r( &R, s ) );
2060
2061 i = mpi_msb( X );
2062 /*
2063 * HAC, table 4.4
2064 */
2065 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2066 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2067 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2068
2069 for( i = 0; i < n; i++ )
2070 {
2071 /*
2072 * pick a random A, 1 < A < |X| - 1
2073 */
Paul Bakker5121ce52009-01-03 21:22:43 +00002074
Pascal Junodb99183d2015-03-11 16:49:45 +01002075 count = 0;
2076 do {
2077 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
2078
2079 j = mpi_msb( &A );
2080 k = mpi_msb( &W );
2081 if (j > k) {
2082 MPI_CHK( mpi_shift_r( &A, j - k ) );
2083 }
2084
2085 if (count++ > 30) {
2086 return POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
2087 }
2088
2089 } while ( (mpi_cmp_mpi( &A, &W ) >= 0) ||
2090 (mpi_cmp_int( &A, 1 ) <= 0) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002091
2092 /*
2093 * A = A^R mod |X|
2094 */
2095 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
2096
2097 if( mpi_cmp_mpi( &A, &W ) == 0 ||
2098 mpi_cmp_int( &A, 1 ) == 0 )
2099 continue;
2100
2101 j = 1;
2102 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
2103 {
2104 /*
2105 * A = A * A mod |X|
2106 */
2107 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
2108 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
2109
2110 if( mpi_cmp_int( &A, 1 ) == 0 )
2111 break;
2112
2113 j++;
2114 }
2115
2116 /*
2117 * not prime if A != |X| - 1 or A == 1
2118 */
2119 if( mpi_cmp_mpi( &A, &W ) != 0 ||
2120 mpi_cmp_int( &A, 1 ) == 0 )
2121 {
Paul Bakker40e46942009-01-03 21:51:57 +00002122 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002123 break;
2124 }
2125 }
2126
2127cleanup:
Paul Bakker6c591fa2011-05-05 11:49:20 +00002128 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
2129 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002130
2131 return( ret );
2132}
2133
2134/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002135 * Pseudo-primality test: small factors, then Miller-Rabin
2136 */
Paul Bakker45f457d2013-11-25 14:26:52 +01002137int mpi_is_prime( mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002138 int (*f_rng)(void *, unsigned char *, size_t),
2139 void *p_rng )
2140{
2141 int ret;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002142 mpi XX;
2143
2144 XX.s = 1;
2145 XX.n = X->n;
2146 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002147
2148 if( mpi_cmp_int( &XX, 0 ) == 0 ||
2149 mpi_cmp_int( &XX, 1 ) == 0 )
2150 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
2151
2152 if( mpi_cmp_int( &XX, 2 ) == 0 )
2153 return( 0 );
2154
2155 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2156 {
2157 if( ret == 1 )
2158 return( 0 );
2159
2160 return( ret );
2161 }
2162
2163 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2164}
2165
2166/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002167 * Prime number generation
2168 */
Paul Bakker23986e52011-04-24 08:57:21 +00002169int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002170 int (*f_rng)(void *, unsigned char *, size_t),
2171 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002172{
Paul Bakker23986e52011-04-24 08:57:21 +00002173 int ret;
2174 size_t k, n;
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002175 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002176 mpi Y;
2177
Paul Bakkerfe3256e2011-11-25 12:11:43 +00002178 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00002179 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002180
Paul Bakker6c591fa2011-05-05 11:49:20 +00002181 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002182
2183 n = BITS_TO_LIMBS( nbits );
2184
Paul Bakker901c6562012-04-20 13:25:38 +00002185 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002186
2187 k = mpi_msb( X );
Pascal Junodb99183d2015-03-11 16:49:45 +01002188 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002189
Pascal Junodb99183d2015-03-11 16:49:45 +01002190 mpi_set_bit( X, nbits-1, 1 );
2191
2192 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002193
2194 if( dh_flag == 0 )
2195 {
2196 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
2197 {
Paul Bakker40e46942009-01-03 21:51:57 +00002198 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002199 goto cleanup;
2200
2201 MPI_CHK( mpi_add_int( X, X, 2 ) );
2202 }
2203 }
2204 else
2205 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002206 /*
2207 * An necessary condition for Y and X = 2Y + 1 to be prime
2208 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2209 * Make sure it is satisfied, while keeping X = 3 mod 4
2210 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002211
2212 X->p[0] |= 2;
2213
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002214 MPI_CHK( mpi_mod_int( &r, X, 3 ) );
2215 if( r == 0 )
2216 MPI_CHK( mpi_add_int( X, X, 8 ) );
2217 else if( r == 1 )
2218 MPI_CHK( mpi_add_int( X, X, 4 ) );
2219
2220 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2221 MPI_CHK( mpi_copy( &Y, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002222 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2223
2224 while( 1 )
2225 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002226 /*
2227 * First, check small factors for X and Y
2228 * before doing Miller-Rabin on any of them
2229 */
2230 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2231 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2232 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2233 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002234 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002235 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002236 }
2237
Paul Bakker40e46942009-01-03 21:51:57 +00002238 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002239 goto cleanup;
2240
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002241 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002242 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002243 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2244 * so up Y by 6 and X by 12.
2245 */
2246 MPI_CHK( mpi_add_int( X, X, 12 ) );
2247 MPI_CHK( mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002248 }
2249 }
2250
2251cleanup:
2252
Paul Bakker6c591fa2011-05-05 11:49:20 +00002253 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002254
2255 return( ret );
2256}
2257
Manuel Pégourié-Gonnarddf0142b2013-08-22 18:29:07 +02002258#endif /* POLARSSL_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002259
Paul Bakker40e46942009-01-03 21:51:57 +00002260#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002261
Paul Bakker23986e52011-04-24 08:57:21 +00002262#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002263
2264static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2265{
2266 { 693, 609, 21 },
2267 { 1764, 868, 28 },
2268 { 768454923, 542167814, 1 }
2269};
2270
Paul Bakker5121ce52009-01-03 21:22:43 +00002271/*
2272 * Checkup routine
2273 */
2274int mpi_self_test( int verbose )
2275{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002276 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002277 mpi A, E, N, X, Y, U, V;
2278
Paul Bakker6c591fa2011-05-05 11:49:20 +00002279 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2280 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002281
2282 MPI_CHK( mpi_read_string( &A, 16,
2283 "EFE021C2645FD1DC586E69184AF4A31E" \
2284 "D5F53E93B5F123FA41680867BA110131" \
2285 "944FE7952E2517337780CB0DB80E61AA" \
2286 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2287
2288 MPI_CHK( mpi_read_string( &E, 16,
2289 "B2E7EFD37075B9F03FF989C7C5051C20" \
2290 "34D2A323810251127E7BF8625A4F49A5" \
2291 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2292 "5B5C25763222FEFCCFC38B832366C29E" ) );
2293
2294 MPI_CHK( mpi_read_string( &N, 16,
2295 "0066A198186C18C10B2F5ED9B522752A" \
2296 "9830B69916E535C8F047518A889A43A5" \
2297 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2298
2299 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2300
2301 MPI_CHK( mpi_read_string( &U, 16,
2302 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2303 "9E857EA95A03512E2BAE7391688D264A" \
2304 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2305 "8001B72E848A38CAE1C65F78E56ABDEF" \
2306 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2307 "ECF677152EF804370C1A305CAF3B5BF1" \
2308 "30879B56C61DE584A0F53A2447A51E" ) );
2309
2310 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002311 polarssl_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002312
2313 if( mpi_cmp_mpi( &X, &U ) != 0 )
2314 {
2315 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002316 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002317
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002318 ret = 1;
2319 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002320 }
2321
2322 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002323 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002324
2325 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2326
2327 MPI_CHK( mpi_read_string( &U, 16,
2328 "256567336059E52CAE22925474705F39A94" ) );
2329
2330 MPI_CHK( mpi_read_string( &V, 16,
2331 "6613F26162223DF488E9CD48CC132C7A" \
2332 "0AC93C701B001B092E4E5B9F73BCD27B" \
2333 "9EE50D0657C77F374E903CDFA4C642" ) );
2334
2335 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002336 polarssl_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002337
2338 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2339 mpi_cmp_mpi( &Y, &V ) != 0 )
2340 {
2341 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002342 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002343
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002344 ret = 1;
2345 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002346 }
2347
2348 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002349 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002350
2351 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2352
2353 MPI_CHK( mpi_read_string( &U, 16,
2354 "36E139AEA55215609D2816998ED020BB" \
2355 "BD96C37890F65171D948E9BC7CBAA4D9" \
2356 "325D24D6A3C12710F10A09FA08AB87" ) );
2357
2358 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002359 polarssl_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
2361 if( mpi_cmp_mpi( &X, &U ) != 0 )
2362 {
2363 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002364 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002365
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002366 ret = 1;
2367 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002368 }
2369
2370 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002371 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002372
2373 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2374
2375 MPI_CHK( mpi_read_string( &U, 16,
2376 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2377 "C3DBA76456363A10869622EAC2DD84EC" \
2378 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2379
2380 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002381 polarssl_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002382
2383 if( mpi_cmp_mpi( &X, &U ) != 0 )
2384 {
2385 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002386 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002387
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002388 ret = 1;
2389 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002390 }
2391
2392 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002393 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002394
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002395 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002396 polarssl_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002397
Paul Bakker66d5d072014-06-17 16:39:18 +02002398 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002399 {
2400 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002401 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002402
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002403 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002404
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002405 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2406 {
2407 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002408 polarssl_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002409
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002410 ret = 1;
2411 goto cleanup;
2412 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002413 }
2414
2415 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002416 polarssl_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002417
Paul Bakker5121ce52009-01-03 21:22:43 +00002418cleanup:
2419
2420 if( ret != 0 && verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002421 polarssl_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002422
Paul Bakker6c591fa2011-05-05 11:49:20 +00002423 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2424 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002425
2426 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002427 polarssl_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002428
2429 return( ret );
2430}
2431
Paul Bakker9af723c2014-05-01 13:03:14 +02002432#endif /* POLARSSL_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002433
Paul Bakker9af723c2014-05-01 13:03:14 +02002434#endif /* POLARSSL_BIGNUM_C */