blob: 4fe841c344e2d4e635a85a3f91af0d0572ac1146 [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;
Manuel Pégourié-Gonnardfaae6d22016-01-08 15:24:46 +0100892 t_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000893
894 if( X == B )
895 {
Janos Follath2db440d2015-10-30 17:43:11 +0100896 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
Janos Follath2db440d2015-10-30 17:43:11 +0100915 /*
916 * tmp is used because it might happen that p == o
917 */
Paul Bakker23986e52011-04-24 08:57:21 +0000918 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000919 {
Janos Follath2db440d2015-10-30 17:43:11 +0100920 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000921 *p += c; c = ( *p < c );
Janos Follath2db440d2015-10-30 17:43:11 +0100922 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000923 }
924
925 while( c != 0 )
926 {
927 if( i >= X->n )
928 {
929 MPI_CHK( mpi_grow( X, i + 1 ) );
930 p = X->p + i;
931 }
932
Paul Bakker2d319fd2012-09-16 21:34:26 +0000933 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000934 }
935
936cleanup:
Paul Bakker5121ce52009-01-03 21:22:43 +0000937 return( ret );
938}
939
940/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100941 * Helper for mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000942 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000943static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000944{
Paul Bakker23986e52011-04-24 08:57:21 +0000945 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000946 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000947
948 for( i = c = 0; i < n; i++, s++, d++ )
949 {
950 z = ( *d < c ); *d -= c;
951 c = ( *d < *s ) + z; *d -= *s;
952 }
953
954 while( c != 0 )
955 {
956 z = ( *d < c ); *d -= c;
957 c = z; i++; d++;
958 }
959}
960
961/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100962 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000963 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000964int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000965{
966 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000967 int ret;
968 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000969
970 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000971 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000972
Paul Bakker6c591fa2011-05-05 11:49:20 +0000973 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000974
975 if( X == B )
976 {
977 MPI_CHK( mpi_copy( &TB, B ) );
978 B = &TB;
979 }
980
981 if( X != A )
982 MPI_CHK( mpi_copy( X, A ) );
983
Paul Bakker1ef7a532009-06-20 10:50:55 +0000984 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100985 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000986 */
987 X->s = 1;
988
Paul Bakker5121ce52009-01-03 21:22:43 +0000989 ret = 0;
990
Paul Bakker23986e52011-04-24 08:57:21 +0000991 for( n = B->n; n > 0; n-- )
992 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000993 break;
994
Paul Bakker23986e52011-04-24 08:57:21 +0000995 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000996
997cleanup:
998
Paul Bakker6c591fa2011-05-05 11:49:20 +0000999 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001000
1001 return( ret );
1002}
1003
1004/*
1005 * Signed addition: X = A + B
1006 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001007int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001008{
1009 int ret, s = A->s;
1010
1011 if( A->s * B->s < 0 )
1012 {
1013 if( mpi_cmp_abs( A, B ) >= 0 )
1014 {
1015 MPI_CHK( mpi_sub_abs( X, A, B ) );
1016 X->s = s;
1017 }
1018 else
1019 {
1020 MPI_CHK( mpi_sub_abs( X, B, A ) );
1021 X->s = -s;
1022 }
1023 }
1024 else
1025 {
1026 MPI_CHK( mpi_add_abs( X, A, B ) );
1027 X->s = s;
1028 }
1029
1030cleanup:
1031
1032 return( ret );
1033}
1034
1035/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001036 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001037 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001038int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001039{
1040 int ret, s = A->s;
1041
1042 if( A->s * B->s > 0 )
1043 {
1044 if( mpi_cmp_abs( A, B ) >= 0 )
1045 {
1046 MPI_CHK( mpi_sub_abs( X, A, B ) );
1047 X->s = s;
1048 }
1049 else
1050 {
1051 MPI_CHK( mpi_sub_abs( X, B, A ) );
1052 X->s = -s;
1053 }
1054 }
1055 else
1056 {
1057 MPI_CHK( mpi_add_abs( X, A, B ) );
1058 X->s = s;
1059 }
1060
1061cleanup:
1062
1063 return( ret );
1064}
1065
1066/*
1067 * Signed addition: X = A + b
1068 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001069int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001070{
1071 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001072 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001073
1074 p[0] = ( b < 0 ) ? -b : b;
1075 _B.s = ( b < 0 ) ? -1 : 1;
1076 _B.n = 1;
1077 _B.p = p;
1078
1079 return( mpi_add_mpi( X, A, &_B ) );
1080}
1081
1082/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001083 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001084 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001085int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001086{
1087 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001088 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001089
1090 p[0] = ( b < 0 ) ? -b : b;
1091 _B.s = ( b < 0 ) ? -1 : 1;
1092 _B.n = 1;
1093 _B.p = p;
1094
1095 return( mpi_sub_mpi( X, A, &_B ) );
1096}
1097
1098/*
1099 * Helper for mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001100 */
1101static
1102#if defined(__APPLE__) && defined(__arm__)
1103/*
1104 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1105 * appears to need this to prevent bad ARM code generation at -O3.
1106 */
1107__attribute__ ((noinline))
1108#endif
1109void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001110{
Paul Bakkera755ca12011-04-24 09:11:17 +00001111 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001112
1113#if defined(MULADDC_HUIT)
1114 for( ; i >= 8; i -= 8 )
1115 {
1116 MULADDC_INIT
1117 MULADDC_HUIT
1118 MULADDC_STOP
1119 }
1120
1121 for( ; i > 0; i-- )
1122 {
1123 MULADDC_INIT
1124 MULADDC_CORE
1125 MULADDC_STOP
1126 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001127#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001128 for( ; i >= 16; i -= 16 )
1129 {
1130 MULADDC_INIT
1131 MULADDC_CORE MULADDC_CORE
1132 MULADDC_CORE MULADDC_CORE
1133 MULADDC_CORE MULADDC_CORE
1134 MULADDC_CORE MULADDC_CORE
1135
1136 MULADDC_CORE MULADDC_CORE
1137 MULADDC_CORE MULADDC_CORE
1138 MULADDC_CORE MULADDC_CORE
1139 MULADDC_CORE MULADDC_CORE
1140 MULADDC_STOP
1141 }
1142
1143 for( ; i >= 8; i -= 8 )
1144 {
1145 MULADDC_INIT
1146 MULADDC_CORE MULADDC_CORE
1147 MULADDC_CORE MULADDC_CORE
1148
1149 MULADDC_CORE MULADDC_CORE
1150 MULADDC_CORE MULADDC_CORE
1151 MULADDC_STOP
1152 }
1153
1154 for( ; i > 0; i-- )
1155 {
1156 MULADDC_INIT
1157 MULADDC_CORE
1158 MULADDC_STOP
1159 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001160#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001161
1162 t++;
1163
1164 do {
1165 *d += c; c = ( *d < c ); d++;
1166 }
1167 while( c != 0 );
1168}
1169
1170/*
1171 * Baseline multiplication: X = A * B (HAC 14.12)
1172 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001173int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001174{
Paul Bakker23986e52011-04-24 08:57:21 +00001175 int ret;
1176 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001177 mpi TA, TB;
1178
Paul Bakker6c591fa2011-05-05 11:49:20 +00001179 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001180
1181 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1182 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1183
Paul Bakker23986e52011-04-24 08:57:21 +00001184 for( i = A->n; i > 0; i-- )
1185 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001186 break;
1187
Paul Bakker23986e52011-04-24 08:57:21 +00001188 for( j = B->n; j > 0; j-- )
1189 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001190 break;
1191
Paul Bakker23986e52011-04-24 08:57:21 +00001192 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001193 MPI_CHK( mpi_lset( X, 0 ) );
1194
Paul Bakker23986e52011-04-24 08:57:21 +00001195 for( i++; j > 0; j-- )
1196 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001197
1198 X->s = A->s * B->s;
1199
1200cleanup:
1201
Paul Bakker6c591fa2011-05-05 11:49:20 +00001202 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001203
1204 return( ret );
1205}
1206
1207/*
1208 * Baseline multiplication: X = A * b
1209 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001210int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001211{
1212 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001213 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001214
1215 _B.s = 1;
1216 _B.n = 1;
1217 _B.p = p;
1218 p[0] = b;
1219
1220 return( mpi_mul_mpi( X, A, &_B ) );
1221}
1222
1223/*
Simon Butcher14400c82016-01-02 00:08:13 +00001224 * Unsigned integer divide - double t_uint, dividend, u1/u0, and t_uint
1225 * divisor, d
Simon Butchere4ed3472015-12-22 15:26:57 +00001226 */
Simon Butcher14400c82016-01-02 00:08:13 +00001227static t_uint int_div_int( t_uint u1, t_uint u0, t_uint d, t_uint *r )
Simon Butchere4ed3472015-12-22 15:26:57 +00001228{
1229#if defined(POLARSSL_HAVE_UDBL)
1230 t_udbl dividend, quotient;
Simon Butcher14400c82016-01-02 00:08:13 +00001231#else
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001232 const t_uint radix = (t_uint) 1 << biH;
1233 const t_uint uint_halfword_mask = ( (t_uint) 1 << biH ) - 1;
Simon Butcher14400c82016-01-02 00:08:13 +00001234 t_uint d0, d1, q0, q1, rAX, r0, quotient;
1235 t_uint u0_msw, u0_lsw;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001236 size_t s;
Simon Butchere4ed3472015-12-22 15:26:57 +00001237#endif
1238
1239 /*
1240 * Check for overflow
1241 */
Simon Butcher14400c82016-01-02 00:08:13 +00001242 if( 0 == d || u1 >= d )
Simon Butchere4ed3472015-12-22 15:26:57 +00001243 {
Simon Butcher14400c82016-01-02 00:08:13 +00001244 if ( r != NULL ) *r = ~0;
Simon Butchere4ed3472015-12-22 15:26:57 +00001245
Simon Butcher14400c82016-01-02 00:08:13 +00001246 return ( ~0 );
Simon Butchere4ed3472015-12-22 15:26:57 +00001247 }
1248
1249#if defined(POLARSSL_HAVE_UDBL)
1250 dividend = (t_udbl) u1 << biL;
1251 dividend |= (t_udbl) u0;
1252 quotient = dividend / d;
1253 if( quotient > ( (t_udbl) 1 << biL ) - 1 )
1254 quotient = ( (t_udbl) 1 << biL ) - 1;
1255
1256 if( r != NULL )
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001257 *r = (t_uint)( dividend - (quotient * d ) );
Simon Butchere4ed3472015-12-22 15:26:57 +00001258
1259 return (t_uint) quotient;
1260#else
Simon Butchere4ed3472015-12-22 15:26:57 +00001261
1262 /*
1263 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1264 * Vol. 2 - Seminumerical Algorithms, Knuth
1265 */
1266
1267 /*
1268 * Normalize the divisor, d, and dividend, u0, u1
1269 */
1270 s = int_clz( d );
1271 d = d << s;
1272
1273 u1 = u1 << s;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001274 u1 |= ( u0 >> ( biL - s ) ) & ( -(t_sint)s >> ( biL - 1 ) );
Simon Butchere4ed3472015-12-22 15:26:57 +00001275 u0 = u0 << s;
1276
1277 d1 = d >> biH;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001278 d0 = d & uint_halfword_mask;
Simon Butchere4ed3472015-12-22 15:26:57 +00001279
1280 u0_msw = u0 >> biH;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001281 u0_lsw = u0 & uint_halfword_mask;
Simon Butchere4ed3472015-12-22 15:26:57 +00001282
1283 /*
1284 * Find the first quotient and remainder
1285 */
1286 q1 = u1 / d1;
1287 r0 = u1 - d1 * q1;
1288
1289 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1290 {
1291 q1 -= 1;
1292 r0 += d1;
1293
1294 if ( r0 >= radix ) break;
1295 }
1296
Simon Butcher14400c82016-01-02 00:08:13 +00001297 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butchere4ed3472015-12-22 15:26:57 +00001298 q0 = rAX / d1;
1299 r0 = rAX - q0 * d1;
1300
1301 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1302 {
1303 q0 -= 1;
1304 r0 += d1;
1305
1306 if ( r0 >= radix ) break;
1307 }
1308
1309 if (r != NULL)
Simon Butcher14400c82016-01-02 00:08:13 +00001310 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butchere4ed3472015-12-22 15:26:57 +00001311
1312 quotient = q1 * radix + q0;
1313
1314 return quotient;
1315#endif
1316}
1317
1318/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001319 * Division by mpi: A = Q * B + R (HAC 14.20)
1320 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001321int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001322{
Paul Bakker23986e52011-04-24 08:57:21 +00001323 int ret;
1324 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001325 mpi X, Y, Z, T1, T2;
1326
1327 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001328 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001329
Paul Bakker6c591fa2011-05-05 11:49:20 +00001330 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1331 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001332
1333 if( mpi_cmp_abs( A, B ) < 0 )
1334 {
1335 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1336 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1337 return( 0 );
1338 }
1339
1340 MPI_CHK( mpi_copy( &X, A ) );
1341 MPI_CHK( mpi_copy( &Y, B ) );
1342 X.s = Y.s = 1;
1343
1344 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1345 MPI_CHK( mpi_lset( &Z, 0 ) );
1346 MPI_CHK( mpi_grow( &T1, 2 ) );
1347 MPI_CHK( mpi_grow( &T2, 3 ) );
1348
1349 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001350 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001351 {
1352 k = biL - 1 - k;
1353 MPI_CHK( mpi_shift_l( &X, k ) );
1354 MPI_CHK( mpi_shift_l( &Y, k ) );
1355 }
1356 else k = 0;
1357
1358 n = X.n - 1;
1359 t = Y.n - 1;
Paul Bakker66d5d072014-06-17 16:39:18 +02001360 MPI_CHK( mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001361
1362 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1363 {
1364 Z.p[n - t]++;
Paul Bakker6ea1a952013-12-31 11:16:03 +01001365 MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001366 }
Paul Bakker66d5d072014-06-17 16:39:18 +02001367 MPI_CHK( mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001368
1369 for( i = n; i > t ; i-- )
1370 {
1371 if( X.p[i] >= Y.p[t] )
1372 Z.p[i - t - 1] = ~0;
1373 else
1374 {
Simon Butchere4ed3472015-12-22 15:26:57 +00001375 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 +00001376 }
1377
1378 Z.p[i - t - 1]++;
1379 do
1380 {
1381 Z.p[i - t - 1]--;
1382
1383 MPI_CHK( mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001384 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001385 T1.p[1] = Y.p[t];
1386 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1387
1388 MPI_CHK( mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001389 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1390 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001391 T2.p[2] = X.p[i];
1392 }
1393 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1394
1395 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001396 MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001397 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1398
1399 if( mpi_cmp_int( &X, 0 ) < 0 )
1400 {
1401 MPI_CHK( mpi_copy( &T1, &Y ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001402 MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001403 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1404 Z.p[i - t - 1]--;
1405 }
1406 }
1407
1408 if( Q != NULL )
1409 {
Paul Bakker6ea1a952013-12-31 11:16:03 +01001410 MPI_CHK( mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001411 Q->s = A->s * B->s;
1412 }
1413
1414 if( R != NULL )
1415 {
Paul Bakker6ea1a952013-12-31 11:16:03 +01001416 MPI_CHK( mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001417 X.s = A->s;
Paul Bakker6ea1a952013-12-31 11:16:03 +01001418 MPI_CHK( mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001419
Paul Bakker5121ce52009-01-03 21:22:43 +00001420 if( mpi_cmp_int( R, 0 ) == 0 )
1421 R->s = 1;
1422 }
1423
1424cleanup:
1425
Paul Bakker6c591fa2011-05-05 11:49:20 +00001426 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1427 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001428
1429 return( ret );
1430}
1431
1432/*
1433 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001434 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001435int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001436{
1437 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001438 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001439
1440 p[0] = ( b < 0 ) ? -b : b;
1441 _B.s = ( b < 0 ) ? -1 : 1;
1442 _B.n = 1;
1443 _B.p = p;
1444
1445 return( mpi_div_mpi( Q, R, A, &_B ) );
1446}
1447
1448/*
1449 * Modulo: R = A mod B
1450 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001451int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001452{
1453 int ret;
1454
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001455 if( mpi_cmp_int( B, 0 ) < 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001456 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001457
Paul Bakker5121ce52009-01-03 21:22:43 +00001458 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1459
1460 while( mpi_cmp_int( R, 0 ) < 0 )
1461 MPI_CHK( mpi_add_mpi( R, R, B ) );
1462
1463 while( mpi_cmp_mpi( R, B ) >= 0 )
1464 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1465
1466cleanup:
1467
1468 return( ret );
1469}
1470
1471/*
1472 * Modulo: r = A mod b
1473 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001474int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001475{
Paul Bakker23986e52011-04-24 08:57:21 +00001476 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001477 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001478
1479 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001480 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001481
1482 if( b < 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001483 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001484
1485 /*
1486 * handle trivial cases
1487 */
1488 if( b == 1 )
1489 {
1490 *r = 0;
1491 return( 0 );
1492 }
1493
1494 if( b == 2 )
1495 {
1496 *r = A->p[0] & 1;
1497 return( 0 );
1498 }
1499
1500 /*
1501 * general case
1502 */
Paul Bakker23986e52011-04-24 08:57:21 +00001503 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001504 {
Paul Bakker23986e52011-04-24 08:57:21 +00001505 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001506 y = ( y << biH ) | ( x >> biH );
1507 z = y / b;
1508 y -= z * b;
1509
1510 x <<= biH;
1511 y = ( y << biH ) | ( x >> biH );
1512 z = y / b;
1513 y -= z * b;
1514 }
1515
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001516 /*
1517 * If A is negative, then the current y represents a negative value.
1518 * Flipping it to the positive side.
1519 */
1520 if( A->s < 0 && y != 0 )
1521 y = b - y;
1522
Paul Bakker5121ce52009-01-03 21:22:43 +00001523 *r = y;
1524
1525 return( 0 );
1526}
1527
1528/*
1529 * Fast Montgomery initialization (thanks to Tom St Denis)
1530 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001531static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001532{
Paul Bakkera755ca12011-04-24 09:11:17 +00001533 t_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001534 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001535
1536 x = m0;
1537 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001538
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001539 for( i = biL; i >= 8; i /= 2 )
1540 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001541
1542 *mm = ~x + 1;
1543}
1544
1545/*
1546 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1547 */
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02001548static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm,
1549 const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001550{
Paul Bakker23986e52011-04-24 08:57:21 +00001551 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001552 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001553
1554 memset( T->p, 0, T->n * ciL );
1555
1556 d = T->p;
1557 n = N->n;
1558 m = ( B->n < n ) ? B->n : n;
1559
1560 for( i = 0; i < n; i++ )
1561 {
1562 /*
1563 * T = (T + u0*B + u1*N) / 2^biL
1564 */
1565 u0 = A->p[i];
1566 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1567
1568 mpi_mul_hlp( m, B->p, d, u0 );
1569 mpi_mul_hlp( n, N->p, d, u1 );
1570
1571 *d++ = u0; d[n + 1] = 0;
1572 }
1573
Paul Bakker66d5d072014-06-17 16:39:18 +02001574 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001575
1576 if( mpi_cmp_abs( A, N ) >= 0 )
1577 mpi_sub_hlp( n, N->p, A->p );
1578 else
1579 /* prevent timing attacks */
1580 mpi_sub_hlp( n, A->p, T->p );
1581}
1582
1583/*
1584 * Montgomery reduction: A = A * R^-1 mod N
1585 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001586static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001587{
Paul Bakkera755ca12011-04-24 09:11:17 +00001588 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001589 mpi U;
1590
Paul Bakker8ddb6452013-02-27 14:56:33 +01001591 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001592 U.p = &z;
1593
1594 mpi_montmul( A, &U, N, mm, T );
1595}
1596
1597/*
1598 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1599 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001600int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001601{
Paul Bakker23986e52011-04-24 08:57:21 +00001602 int ret;
1603 size_t wbits, wsize, one = 1;
1604 size_t i, j, nblimbs;
1605 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001606 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001607 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1608 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001609
1610 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001611 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001612
Paul Bakkerf6198c12012-05-16 08:02:29 +00001613 if( mpi_cmp_int( E, 0 ) < 0 )
1614 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1615
1616 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001617 * Init temps and window size
1618 */
1619 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001620 mpi_init( &RR ); mpi_init( &T );
Manuel Pégourié-Gonnardfd6a1912014-01-18 19:05:23 +01001621 mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001622 memset( W, 0, sizeof( W ) );
1623
1624 i = mpi_msb( E );
1625
1626 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1627 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1628
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001629 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1630 wsize = POLARSSL_MPI_WINDOW_SIZE;
1631
Paul Bakker5121ce52009-01-03 21:22:43 +00001632 j = N->n + 1;
1633 MPI_CHK( mpi_grow( X, j ) );
1634 MPI_CHK( mpi_grow( &W[1], j ) );
1635 MPI_CHK( mpi_grow( &T, j * 2 ) );
1636
1637 /*
Paul Bakker50546922012-05-19 08:40:49 +00001638 * Compensate for negative A (and correct at the end)
1639 */
1640 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001641 if( neg )
1642 {
1643 MPI_CHK( mpi_copy( &Apos, A ) );
1644 Apos.s = 1;
1645 A = &Apos;
1646 }
1647
1648 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001649 * If 1st call, pre-compute R^2 mod N
1650 */
1651 if( _RR == NULL || _RR->p == NULL )
1652 {
1653 MPI_CHK( mpi_lset( &RR, 1 ) );
1654 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1655 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1656
1657 if( _RR != NULL )
1658 memcpy( _RR, &RR, sizeof( mpi ) );
1659 }
1660 else
1661 memcpy( &RR, _RR, sizeof( mpi ) );
1662
1663 /*
1664 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1665 */
1666 if( mpi_cmp_mpi( A, N ) >= 0 )
Paul Bakkerc2024f42014-01-23 20:38:35 +01001667 MPI_CHK( mpi_mod_mpi( &W[1], A, N ) );
1668 else
1669 MPI_CHK( mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001670
1671 mpi_montmul( &W[1], &RR, N, mm, &T );
1672
1673 /*
1674 * X = R^2 * R^-1 mod N = R mod N
1675 */
1676 MPI_CHK( mpi_copy( X, &RR ) );
1677 mpi_montred( X, N, mm, &T );
1678
1679 if( wsize > 1 )
1680 {
1681 /*
1682 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1683 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001684 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001685
1686 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1687 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1688
1689 for( i = 0; i < wsize - 1; i++ )
1690 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001691
Paul Bakker5121ce52009-01-03 21:22:43 +00001692 /*
1693 * W[i] = W[i - 1] * W[1]
1694 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001695 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001696 {
1697 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1698 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1699
1700 mpi_montmul( &W[i], &W[1], N, mm, &T );
1701 }
1702 }
1703
1704 nblimbs = E->n;
1705 bufsize = 0;
1706 nbits = 0;
1707 wbits = 0;
1708 state = 0;
1709
1710 while( 1 )
1711 {
1712 if( bufsize == 0 )
1713 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001714 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001715 break;
1716
Paul Bakker0d7702c2013-10-29 16:18:35 +01001717 nblimbs--;
1718
Paul Bakkera755ca12011-04-24 09:11:17 +00001719 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001720 }
1721
1722 bufsize--;
1723
1724 ei = (E->p[nblimbs] >> bufsize) & 1;
1725
1726 /*
1727 * skip leading 0s
1728 */
1729 if( ei == 0 && state == 0 )
1730 continue;
1731
1732 if( ei == 0 && state == 1 )
1733 {
1734 /*
1735 * out of window, square X
1736 */
1737 mpi_montmul( X, X, N, mm, &T );
1738 continue;
1739 }
1740
1741 /*
1742 * add ei to current window
1743 */
1744 state = 2;
1745
1746 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001747 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001748
1749 if( nbits == wsize )
1750 {
1751 /*
1752 * X = X^wsize R^-1 mod N
1753 */
1754 for( i = 0; i < wsize; i++ )
1755 mpi_montmul( X, X, N, mm, &T );
1756
1757 /*
1758 * X = X * W[wbits] R^-1 mod N
1759 */
1760 mpi_montmul( X, &W[wbits], N, mm, &T );
1761
1762 state--;
1763 nbits = 0;
1764 wbits = 0;
1765 }
1766 }
1767
1768 /*
1769 * process the remaining bits
1770 */
1771 for( i = 0; i < nbits; i++ )
1772 {
1773 mpi_montmul( X, X, N, mm, &T );
1774
1775 wbits <<= 1;
1776
Paul Bakker66d5d072014-06-17 16:39:18 +02001777 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001778 mpi_montmul( X, &W[1], N, mm, &T );
1779 }
1780
1781 /*
1782 * X = A^E * R * R^-1 mod N = A^E mod N
1783 */
1784 mpi_montred( X, N, mm, &T );
1785
Paul Bakkerf6198c12012-05-16 08:02:29 +00001786 if( neg )
1787 {
1788 X->s = -1;
Paul Bakkerc2024f42014-01-23 20:38:35 +01001789 MPI_CHK( mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001790 }
1791
Paul Bakker5121ce52009-01-03 21:22:43 +00001792cleanup:
1793
Paul Bakker66d5d072014-06-17 16:39:18 +02001794 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001795 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001796
Paul Bakkerf6198c12012-05-16 08:02:29 +00001797 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001798
Paul Bakker75a28602014-03-31 12:08:17 +02001799 if( _RR == NULL || _RR->p == NULL )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001800 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001801
1802 return( ret );
1803}
1804
Paul Bakker5121ce52009-01-03 21:22:43 +00001805/*
1806 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1807 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001808int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001809{
Paul Bakker23986e52011-04-24 08:57:21 +00001810 int ret;
1811 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001812 mpi TG, TA, TB;
1813
Paul Bakker6c591fa2011-05-05 11:49:20 +00001814 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001815
Paul Bakker5121ce52009-01-03 21:22:43 +00001816 MPI_CHK( mpi_copy( &TA, A ) );
1817 MPI_CHK( mpi_copy( &TB, B ) );
1818
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001819 lz = mpi_lsb( &TA );
1820 lzt = mpi_lsb( &TB );
1821
Paul Bakker66d5d072014-06-17 16:39:18 +02001822 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001823 lz = lzt;
1824
1825 MPI_CHK( mpi_shift_r( &TA, lz ) );
1826 MPI_CHK( mpi_shift_r( &TB, lz ) );
1827
Paul Bakker5121ce52009-01-03 21:22:43 +00001828 TA.s = TB.s = 1;
1829
1830 while( mpi_cmp_int( &TA, 0 ) != 0 )
1831 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001832 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1833 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001834
1835 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1836 {
1837 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1838 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1839 }
1840 else
1841 {
1842 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1843 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1844 }
1845 }
1846
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001847 MPI_CHK( mpi_shift_l( &TB, lz ) );
1848 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001849
1850cleanup:
1851
Paul Bakker6c591fa2011-05-05 11:49:20 +00001852 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001853
1854 return( ret );
1855}
1856
Paul Bakker33dc46b2014-04-30 16:11:39 +02001857/*
1858 * Fill X with size bytes of random.
1859 *
1860 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001861 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001862 * deterministic, eg for tests).
1863 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001864int mpi_fill_random( mpi *X, size_t size,
1865 int (*f_rng)(void *, unsigned char *, size_t),
1866 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001867{
Paul Bakker23986e52011-04-24 08:57:21 +00001868 int ret;
Paul Bakker33dc46b2014-04-30 16:11:39 +02001869 unsigned char buf[POLARSSL_MPI_MAX_SIZE];
1870
1871 if( size > POLARSSL_MPI_MAX_SIZE )
1872 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001873
Paul Bakker33dc46b2014-04-30 16:11:39 +02001874 MPI_CHK( f_rng( p_rng, buf, size ) );
1875 MPI_CHK( mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001876
1877cleanup:
1878 return( ret );
1879}
1880
Paul Bakker5121ce52009-01-03 21:22:43 +00001881/*
1882 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1883 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001884int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001885{
1886 int ret;
1887 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1888
1889 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001890 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001891
Paul Bakker6c591fa2011-05-05 11:49:20 +00001892 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1893 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1894 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001895
1896 MPI_CHK( mpi_gcd( &G, A, N ) );
1897
1898 if( mpi_cmp_int( &G, 1 ) != 0 )
1899 {
Paul Bakker40e46942009-01-03 21:51:57 +00001900 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001901 goto cleanup;
1902 }
1903
1904 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1905 MPI_CHK( mpi_copy( &TU, &TA ) );
1906 MPI_CHK( mpi_copy( &TB, N ) );
1907 MPI_CHK( mpi_copy( &TV, N ) );
1908
1909 MPI_CHK( mpi_lset( &U1, 1 ) );
1910 MPI_CHK( mpi_lset( &U2, 0 ) );
1911 MPI_CHK( mpi_lset( &V1, 0 ) );
1912 MPI_CHK( mpi_lset( &V2, 1 ) );
1913
1914 do
1915 {
1916 while( ( TU.p[0] & 1 ) == 0 )
1917 {
1918 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1919
1920 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1921 {
1922 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1923 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1924 }
1925
1926 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1927 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1928 }
1929
1930 while( ( TV.p[0] & 1 ) == 0 )
1931 {
1932 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1933
1934 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1935 {
1936 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1937 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1938 }
1939
1940 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1941 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1942 }
1943
1944 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1945 {
1946 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1947 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1948 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1949 }
1950 else
1951 {
1952 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1953 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1954 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1955 }
1956 }
1957 while( mpi_cmp_int( &TU, 0 ) != 0 );
1958
1959 while( mpi_cmp_int( &V1, 0 ) < 0 )
1960 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1961
1962 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1963 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1964
1965 MPI_CHK( mpi_copy( X, &V1 ) );
1966
1967cleanup:
1968
Paul Bakker6c591fa2011-05-05 11:49:20 +00001969 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1970 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1971 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001972
1973 return( ret );
1974}
1975
Paul Bakkerd9374b02012-11-02 11:02:58 +00001976#if defined(POLARSSL_GENPRIME)
1977
Paul Bakker5121ce52009-01-03 21:22:43 +00001978static const int small_prime[] =
1979{
1980 3, 5, 7, 11, 13, 17, 19, 23,
1981 29, 31, 37, 41, 43, 47, 53, 59,
1982 61, 67, 71, 73, 79, 83, 89, 97,
1983 101, 103, 107, 109, 113, 127, 131, 137,
1984 139, 149, 151, 157, 163, 167, 173, 179,
1985 181, 191, 193, 197, 199, 211, 223, 227,
1986 229, 233, 239, 241, 251, 257, 263, 269,
1987 271, 277, 281, 283, 293, 307, 311, 313,
1988 317, 331, 337, 347, 349, 353, 359, 367,
1989 373, 379, 383, 389, 397, 401, 409, 419,
1990 421, 431, 433, 439, 443, 449, 457, 461,
1991 463, 467, 479, 487, 491, 499, 503, 509,
1992 521, 523, 541, 547, 557, 563, 569, 571,
1993 577, 587, 593, 599, 601, 607, 613, 617,
1994 619, 631, 641, 643, 647, 653, 659, 661,
1995 673, 677, 683, 691, 701, 709, 719, 727,
1996 733, 739, 743, 751, 757, 761, 769, 773,
1997 787, 797, 809, 811, 821, 823, 827, 829,
1998 839, 853, 857, 859, 863, 877, 881, 883,
1999 887, 907, 911, 919, 929, 937, 941, 947,
2000 953, 967, 971, 977, 983, 991, 997, -103
2001};
2002
2003/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002004 * Small divisors test (X must be positive)
2005 *
2006 * Return values:
2007 * 0: no small factor (possible prime, more tests needed)
2008 * 1: certain prime
2009 * POLARSSL_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2010 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002011 */
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002012static int mpi_check_small_factors( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002013{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002014 int ret = 0;
2015 size_t i;
2016 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002017
Paul Bakker5121ce52009-01-03 21:22:43 +00002018 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002019 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002020
2021 for( i = 0; small_prime[i] > 0; i++ )
2022 {
Paul Bakker5121ce52009-01-03 21:22:43 +00002023 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002024 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002025
2026 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
2027
2028 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002029 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002030 }
2031
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002032cleanup:
2033 return( ret );
2034}
2035
2036/*
2037 * Miller-Rabin pseudo-primality test (HAC 4.24)
2038 */
2039static int mpi_miller_rabin( const mpi *X,
2040 int (*f_rng)(void *, unsigned char *, size_t),
2041 void *p_rng )
2042{
Pascal Junodb99183d2015-03-11 16:49:45 +01002043 int ret, count;
2044 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002045 mpi W, R, T, A, RR;
2046
2047 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
2048 mpi_init( &RR );
2049
Paul Bakker5121ce52009-01-03 21:22:43 +00002050 /*
2051 * W = |X| - 1
2052 * R = W >> lsb( W )
2053 */
Paul Bakker5121ce52009-01-03 21:22:43 +00002054 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00002055 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00002056 MPI_CHK( mpi_copy( &R, &W ) );
2057 MPI_CHK( mpi_shift_r( &R, s ) );
2058
2059 i = mpi_msb( X );
2060 /*
2061 * HAC, table 4.4
2062 */
2063 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2064 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2065 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2066
2067 for( i = 0; i < n; i++ )
2068 {
2069 /*
2070 * pick a random A, 1 < A < |X| - 1
2071 */
Paul Bakker5121ce52009-01-03 21:22:43 +00002072
Pascal Junodb99183d2015-03-11 16:49:45 +01002073 count = 0;
2074 do {
2075 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
2076
2077 j = mpi_msb( &A );
2078 k = mpi_msb( &W );
2079 if (j > k) {
2080 MPI_CHK( mpi_shift_r( &A, j - k ) );
2081 }
2082
2083 if (count++ > 30) {
2084 return POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
2085 }
2086
2087 } while ( (mpi_cmp_mpi( &A, &W ) >= 0) ||
2088 (mpi_cmp_int( &A, 1 ) <= 0) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002089
2090 /*
2091 * A = A^R mod |X|
2092 */
2093 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
2094
2095 if( mpi_cmp_mpi( &A, &W ) == 0 ||
2096 mpi_cmp_int( &A, 1 ) == 0 )
2097 continue;
2098
2099 j = 1;
2100 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
2101 {
2102 /*
2103 * A = A * A mod |X|
2104 */
2105 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
2106 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
2107
2108 if( mpi_cmp_int( &A, 1 ) == 0 )
2109 break;
2110
2111 j++;
2112 }
2113
2114 /*
2115 * not prime if A != |X| - 1 or A == 1
2116 */
2117 if( mpi_cmp_mpi( &A, &W ) != 0 ||
2118 mpi_cmp_int( &A, 1 ) == 0 )
2119 {
Paul Bakker40e46942009-01-03 21:51:57 +00002120 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002121 break;
2122 }
2123 }
2124
2125cleanup:
Paul Bakker6c591fa2011-05-05 11:49:20 +00002126 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
2127 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002128
2129 return( ret );
2130}
2131
2132/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002133 * Pseudo-primality test: small factors, then Miller-Rabin
2134 */
Paul Bakker45f457d2013-11-25 14:26:52 +01002135int mpi_is_prime( mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002136 int (*f_rng)(void *, unsigned char *, size_t),
2137 void *p_rng )
2138{
2139 int ret;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002140 mpi XX;
2141
2142 XX.s = 1;
2143 XX.n = X->n;
2144 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002145
2146 if( mpi_cmp_int( &XX, 0 ) == 0 ||
2147 mpi_cmp_int( &XX, 1 ) == 0 )
2148 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
2149
2150 if( mpi_cmp_int( &XX, 2 ) == 0 )
2151 return( 0 );
2152
2153 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2154 {
2155 if( ret == 1 )
2156 return( 0 );
2157
2158 return( ret );
2159 }
2160
2161 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2162}
2163
2164/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002165 * Prime number generation
2166 */
Paul Bakker23986e52011-04-24 08:57:21 +00002167int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002168 int (*f_rng)(void *, unsigned char *, size_t),
2169 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002170{
Paul Bakker23986e52011-04-24 08:57:21 +00002171 int ret;
2172 size_t k, n;
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002173 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002174 mpi Y;
2175
Paul Bakkerfe3256e2011-11-25 12:11:43 +00002176 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00002177 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002178
Paul Bakker6c591fa2011-05-05 11:49:20 +00002179 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002180
2181 n = BITS_TO_LIMBS( nbits );
2182
Paul Bakker901c6562012-04-20 13:25:38 +00002183 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002184
2185 k = mpi_msb( X );
Pascal Junodb99183d2015-03-11 16:49:45 +01002186 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002187
Pascal Junodb99183d2015-03-11 16:49:45 +01002188 mpi_set_bit( X, nbits-1, 1 );
2189
2190 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002191
2192 if( dh_flag == 0 )
2193 {
2194 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
2195 {
Paul Bakker40e46942009-01-03 21:51:57 +00002196 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002197 goto cleanup;
2198
2199 MPI_CHK( mpi_add_int( X, X, 2 ) );
2200 }
2201 }
2202 else
2203 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002204 /*
2205 * An necessary condition for Y and X = 2Y + 1 to be prime
2206 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2207 * Make sure it is satisfied, while keeping X = 3 mod 4
2208 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002209
2210 X->p[0] |= 2;
2211
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002212 MPI_CHK( mpi_mod_int( &r, X, 3 ) );
2213 if( r == 0 )
2214 MPI_CHK( mpi_add_int( X, X, 8 ) );
2215 else if( r == 1 )
2216 MPI_CHK( mpi_add_int( X, X, 4 ) );
2217
2218 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2219 MPI_CHK( mpi_copy( &Y, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002220 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2221
2222 while( 1 )
2223 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002224 /*
2225 * First, check small factors for X and Y
2226 * before doing Miller-Rabin on any of them
2227 */
2228 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2229 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2230 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2231 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002232 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002233 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002234 }
2235
Paul Bakker40e46942009-01-03 21:51:57 +00002236 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002237 goto cleanup;
2238
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002239 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002240 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002241 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2242 * so up Y by 6 and X by 12.
2243 */
2244 MPI_CHK( mpi_add_int( X, X, 12 ) );
2245 MPI_CHK( mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002246 }
2247 }
2248
2249cleanup:
2250
Paul Bakker6c591fa2011-05-05 11:49:20 +00002251 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002252
2253 return( ret );
2254}
2255
Manuel Pégourié-Gonnarddf0142b2013-08-22 18:29:07 +02002256#endif /* POLARSSL_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002257
Paul Bakker40e46942009-01-03 21:51:57 +00002258#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002259
Paul Bakker23986e52011-04-24 08:57:21 +00002260#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002261
2262static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2263{
2264 { 693, 609, 21 },
2265 { 1764, 868, 28 },
2266 { 768454923, 542167814, 1 }
2267};
2268
Paul Bakker5121ce52009-01-03 21:22:43 +00002269/*
2270 * Checkup routine
2271 */
2272int mpi_self_test( int verbose )
2273{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002274 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002275 mpi A, E, N, X, Y, U, V;
2276
Paul Bakker6c591fa2011-05-05 11:49:20 +00002277 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2278 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002279
2280 MPI_CHK( mpi_read_string( &A, 16,
2281 "EFE021C2645FD1DC586E69184AF4A31E" \
2282 "D5F53E93B5F123FA41680867BA110131" \
2283 "944FE7952E2517337780CB0DB80E61AA" \
2284 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2285
2286 MPI_CHK( mpi_read_string( &E, 16,
2287 "B2E7EFD37075B9F03FF989C7C5051C20" \
2288 "34D2A323810251127E7BF8625A4F49A5" \
2289 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2290 "5B5C25763222FEFCCFC38B832366C29E" ) );
2291
2292 MPI_CHK( mpi_read_string( &N, 16,
2293 "0066A198186C18C10B2F5ED9B522752A" \
2294 "9830B69916E535C8F047518A889A43A5" \
2295 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2296
2297 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2298
2299 MPI_CHK( mpi_read_string( &U, 16,
2300 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2301 "9E857EA95A03512E2BAE7391688D264A" \
2302 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2303 "8001B72E848A38CAE1C65F78E56ABDEF" \
2304 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2305 "ECF677152EF804370C1A305CAF3B5BF1" \
2306 "30879B56C61DE584A0F53A2447A51E" ) );
2307
2308 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002309 polarssl_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002310
2311 if( mpi_cmp_mpi( &X, &U ) != 0 )
2312 {
2313 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002314 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002315
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002316 ret = 1;
2317 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002318 }
2319
2320 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002321 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002322
2323 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2324
2325 MPI_CHK( mpi_read_string( &U, 16,
2326 "256567336059E52CAE22925474705F39A94" ) );
2327
2328 MPI_CHK( mpi_read_string( &V, 16,
2329 "6613F26162223DF488E9CD48CC132C7A" \
2330 "0AC93C701B001B092E4E5B9F73BCD27B" \
2331 "9EE50D0657C77F374E903CDFA4C642" ) );
2332
2333 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002334 polarssl_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002335
2336 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2337 mpi_cmp_mpi( &Y, &V ) != 0 )
2338 {
2339 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002340 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002341
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002342 ret = 1;
2343 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002344 }
2345
2346 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002347 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002348
2349 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2350
2351 MPI_CHK( mpi_read_string( &U, 16,
2352 "36E139AEA55215609D2816998ED020BB" \
2353 "BD96C37890F65171D948E9BC7CBAA4D9" \
2354 "325D24D6A3C12710F10A09FA08AB87" ) );
2355
2356 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002357 polarssl_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002358
2359 if( mpi_cmp_mpi( &X, &U ) != 0 )
2360 {
2361 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002362 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002363
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002364 ret = 1;
2365 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002366 }
2367
2368 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002369 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002370
2371 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2372
2373 MPI_CHK( mpi_read_string( &U, 16,
2374 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2375 "C3DBA76456363A10869622EAC2DD84EC" \
2376 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2377
2378 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002379 polarssl_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002380
2381 if( mpi_cmp_mpi( &X, &U ) != 0 )
2382 {
2383 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002384 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002385
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002386 ret = 1;
2387 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002388 }
2389
2390 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002391 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002392
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002393 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002394 polarssl_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002395
Paul Bakker66d5d072014-06-17 16:39:18 +02002396 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002397 {
2398 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002399 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002400
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002401 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002402
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002403 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2404 {
2405 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002406 polarssl_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002407
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002408 ret = 1;
2409 goto cleanup;
2410 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002411 }
2412
2413 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002414 polarssl_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002415
Paul Bakker5121ce52009-01-03 21:22:43 +00002416cleanup:
2417
2418 if( ret != 0 && verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002419 polarssl_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002420
Paul Bakker6c591fa2011-05-05 11:49:20 +00002421 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2422 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002423
2424 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002425 polarssl_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002426
2427 return( ret );
2428}
2429
Paul Bakker9af723c2014-05-01 13:03:14 +02002430#endif /* POLARSSL_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002431
Paul Bakker9af723c2014-05-01 13:03:14 +02002432#endif /* POLARSSL_BIGNUM_C */