blob: 975b6f8b42faf7d2e0f91d58a57cdfef18b5ae35 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
Paul Bakkerb96f1542010-07-18 20:36:00 +00005 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +00006 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakkerb96f1542010-07-18 20:36:00 +00007 *
Paul Bakker5121ce52009-01-03 21:22:43 +00008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
Simon Butchere4ed3472015-12-22 15:26:57 +000022
Paul Bakker5121ce52009-01-03 21:22:43 +000023/*
Simon Butchere4ed3472015-12-22 15:26:57 +000024 * The following sources were referenced in the design of this Multi-precision
25 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000026 *
Simon Butchere4ed3472015-12-22 15:26:57 +000027 * [1] Handbook of Applied Cryptography - 1997
28 * Menezes, van Oorschot and Vanstone
29 *
30 * [2] Multi-Precision Math
31 * Tom St Denis
32 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
33 *
34 * [3] GNU Multi-Precision Arithmetic Library
35 * https://gmplib.org/manual/index.html
36 *
Simon Butcher14400c82016-01-02 00:08:13 +000037 */
Paul Bakker5121ce52009-01-03 21:22:43 +000038
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020039#if !defined(POLARSSL_CONFIG_FILE)
Paul Bakker40e46942009-01-03 21:51:57 +000040#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020041#else
42#include POLARSSL_CONFIG_FILE
43#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000044
Paul Bakker40e46942009-01-03 21:51:57 +000045#if defined(POLARSSL_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000046
Paul Bakker40e46942009-01-03 21:51:57 +000047#include "polarssl/bignum.h"
48#include "polarssl/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000049
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <string.h>
51
Paul Bakker7dc4c442014-02-01 22:50:26 +010052#if defined(POLARSSL_PLATFORM_C)
53#include "polarssl/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020054#else
Rich Evans00ab4702015-02-06 13:43:58 +000055#include <stdio.h>
56#include <stdlib.h>
Paul Bakker7dc4c442014-02-01 22:50:26 +010057#define polarssl_printf printf
Paul Bakker6e339b52013-07-03 13:37:05 +020058#define polarssl_malloc malloc
59#define polarssl_free free
60#endif
61
Paul Bakker34617722014-06-13 17:20:13 +020062/* Implementation that should never be optimized out by the compiler */
63static void polarssl_zeroize( void *v, size_t n ) {
64 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
65}
66
Paul Bakkerf9688572011-05-05 10:00:45 +000067#define ciL (sizeof(t_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000068#define biL (ciL << 3) /* bits in limb */
69#define biH (ciL << 2) /* half limb size */
70
Manuel Pégourié-Gonnardfa647a72015-10-05 15:23:11 +010071#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
72
Paul Bakker5121ce52009-01-03 21:22:43 +000073/*
74 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard59efb6a2015-09-28 13:48:04 +020075 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000076 */
Manuel Pégourié-Gonnard59efb6a2015-09-28 13:48:04 +020077#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
78#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000079
80/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000081 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000082 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000083void mpi_init( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000084{
Paul Bakker6c591fa2011-05-05 11:49:20 +000085 if( X == NULL )
86 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000087
Paul Bakker6c591fa2011-05-05 11:49:20 +000088 X->s = 1;
89 X->n = 0;
90 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000091}
92
93/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000094 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000095 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000096void mpi_free( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000097{
Paul Bakker6c591fa2011-05-05 11:49:20 +000098 if( X == NULL )
99 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000100
Paul Bakker6c591fa2011-05-05 11:49:20 +0000101 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102 {
Paul Bakker34617722014-06-13 17:20:13 +0200103 polarssl_zeroize( X->p, X->n * ciL );
Paul Bakker6e339b52013-07-03 13:37:05 +0200104 polarssl_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000105 }
106
Paul Bakker6c591fa2011-05-05 11:49:20 +0000107 X->s = 1;
108 X->n = 0;
109 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000110}
111
112/*
113 * Enlarge to the specified number of limbs
114 */
Paul Bakker23986e52011-04-24 08:57:21 +0000115int mpi_grow( mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000116{
Paul Bakkera755ca12011-04-24 09:11:17 +0000117 t_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000118
Paul Bakkerf9688572011-05-05 10:00:45 +0000119 if( nblimbs > POLARSSL_MPI_MAX_LIMBS )
Paul Bakker69e095c2011-12-10 21:55:01 +0000120 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000121
Paul Bakker5121ce52009-01-03 21:22:43 +0000122 if( X->n < nblimbs )
123 {
Mansour Moufidc531b4a2015-02-15 17:35:38 -0500124 if( ( p = polarssl_malloc( nblimbs * ciL ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000125 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000126
127 memset( p, 0, nblimbs * ciL );
128
129 if( X->p != NULL )
130 {
131 memcpy( p, X->p, X->n * ciL );
Paul Bakker34617722014-06-13 17:20:13 +0200132 polarssl_zeroize( X->p, X->n * ciL );
Paul Bakker6e339b52013-07-03 13:37:05 +0200133 polarssl_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000134 }
135
136 X->n = nblimbs;
137 X->p = p;
138 }
139
140 return( 0 );
141}
142
143/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100144 * Resize down as much as possible,
145 * while keeping at least the specified number of limbs
146 */
147int mpi_shrink( mpi *X, size_t nblimbs )
148{
149 t_uint *p;
150 size_t i;
151
152 /* Actually resize up in this case */
153 if( X->n <= nblimbs )
154 return( mpi_grow( X, nblimbs ) );
155
156 for( i = X->n - 1; i > 0; i-- )
157 if( X->p[i] != 0 )
158 break;
159 i++;
160
161 if( i < nblimbs )
162 i = nblimbs;
163
Mansour Moufidc531b4a2015-02-15 17:35:38 -0500164 if( ( p = polarssl_malloc( i * ciL ) ) == NULL )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100165 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
166
167 memset( p, 0, i * ciL );
168
169 if( X->p != NULL )
170 {
171 memcpy( p, X->p, i * ciL );
Paul Bakker34617722014-06-13 17:20:13 +0200172 polarssl_zeroize( X->p, X->n * ciL );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100173 polarssl_free( X->p );
174 }
175
176 X->n = i;
177 X->p = p;
178
179 return( 0 );
180}
181
182/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000183 * Copy the contents of Y into X
184 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000185int mpi_copy( mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000186{
Paul Bakker23986e52011-04-24 08:57:21 +0000187 int ret;
188 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000189
190 if( X == Y )
191 return( 0 );
192
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200193 if( Y->p == NULL )
194 {
195 mpi_free( X );
196 return( 0 );
197 }
198
Paul Bakker5121ce52009-01-03 21:22:43 +0000199 for( i = Y->n - 1; i > 0; i-- )
200 if( Y->p[i] != 0 )
201 break;
202 i++;
203
204 X->s = Y->s;
205
206 MPI_CHK( mpi_grow( X, i ) );
207
208 memset( X->p, 0, X->n * ciL );
209 memcpy( X->p, Y->p, i * ciL );
210
211cleanup:
212
213 return( ret );
214}
215
216/*
217 * Swap the contents of X and Y
218 */
219void mpi_swap( mpi *X, mpi *Y )
220{
221 mpi T;
222
223 memcpy( &T, X, sizeof( mpi ) );
224 memcpy( X, Y, sizeof( mpi ) );
225 memcpy( Y, &T, sizeof( mpi ) );
226}
227
228/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100229 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100230 * about whether the assignment was made or not.
231 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100232 */
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100233int mpi_safe_cond_assign( mpi *X, const mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100234{
235 int ret = 0;
236 size_t i;
237
Pascal Junodb99183d2015-03-11 16:49:45 +0100238 /* make sure assign is 0 or 1 in a time-constant manner */
239 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100240
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100241 MPI_CHK( mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100242
Paul Bakker66d5d072014-06-17 16:39:18 +0200243 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100244
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100245 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200246 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100247
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100248 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200249 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250
251cleanup:
252 return( ret );
253}
254
255/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100256 * Conditionally swap X and Y, without leaking information
257 * about whether the swap was made or not.
258 * Here it is not ok to simply swap the pointers, which whould lead to
259 * different memory access patterns when X and Y are used afterwards.
260 */
261int mpi_safe_cond_swap( mpi *X, mpi *Y, unsigned char swap )
262{
263 int ret, s;
264 size_t i;
265 t_uint tmp;
266
267 if( X == Y )
268 return( 0 );
269
Pascal Junodb99183d2015-03-11 16:49:45 +0100270 /* make sure swap is 0 or 1 in a time-constant manner */
271 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100272
273 MPI_CHK( mpi_grow( X, Y->n ) );
274 MPI_CHK( mpi_grow( Y, X->n ) );
275
276 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200277 X->s = X->s * ( 1 - swap ) + Y->s * swap;
278 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100279
280
281 for( i = 0; i < X->n; i++ )
282 {
283 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200284 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
285 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286 }
287
288cleanup:
289 return( ret );
290}
291
292/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000293 * Set value from integer
294 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000295int mpi_lset( mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000296{
297 int ret;
298
299 MPI_CHK( mpi_grow( X, 1 ) );
300 memset( X->p, 0, X->n * ciL );
301
302 X->p[0] = ( z < 0 ) ? -z : z;
303 X->s = ( z < 0 ) ? -1 : 1;
304
305cleanup:
306
307 return( ret );
308}
309
310/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000311 * Get a specific bit
312 */
Paul Bakker6b906e52012-05-08 12:01:43 +0000313int mpi_get_bit( const mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000314{
315 if( X->n * biL <= pos )
316 return( 0 );
317
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200318 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000319}
320
321/*
322 * Set a bit to a specific value of 0 or 1
323 */
324int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
325{
326 int ret = 0;
327 size_t off = pos / biL;
328 size_t idx = pos % biL;
329
330 if( val != 0 && val != 1 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200331 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200332
Paul Bakker2f5947e2011-05-18 15:47:11 +0000333 if( X->n * biL <= pos )
334 {
335 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200336 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000337
338 MPI_CHK( mpi_grow( X, off + 1 ) );
339 }
340
Manuel Pégourié-Gonnard9a4a5ac2013-12-04 18:05:29 +0100341 X->p[off] &= ~( (t_uint) 0x01 << idx );
342 X->p[off] |= (t_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000343
344cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200345
Paul Bakker2f5947e2011-05-18 15:47:11 +0000346 return( ret );
347}
348
349/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000350 * Return the number of least significant bits
351 */
Paul Bakker23986e52011-04-24 08:57:21 +0000352size_t mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000353{
Paul Bakker23986e52011-04-24 08:57:21 +0000354 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000355
356 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000357 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000358 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
359 return( count );
360
361 return( 0 );
362}
363
364/*
Simon Butchere4ed3472015-12-22 15:26:57 +0000365 * Count leading zero bits in a given integer
366 */
367static size_t int_clz( const t_uint x )
368{
369 size_t j;
370 t_uint mask = (t_uint) 1 << (biL - 1);
371
372 for( j = 0; j < biL; j++ )
373 {
374 if( x & mask ) break;
375
376 mask >>= 1;
377 }
378
379 return j;
380}
381
382/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000383 * Return the number of most significant bits
384 */
Paul Bakker23986e52011-04-24 08:57:21 +0000385size_t mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000386{
Paul Bakker23986e52011-04-24 08:57:21 +0000387 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000388
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200389 if( X->n == 0 )
390 return( 0 );
391
Paul Bakker5121ce52009-01-03 21:22:43 +0000392 for( i = X->n - 1; i > 0; i-- )
393 if( X->p[i] != 0 )
394 break;
395
Simon Butchere4ed3472015-12-22 15:26:57 +0000396 j = biL - int_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000397
Paul Bakker23986e52011-04-24 08:57:21 +0000398 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000399}
400
401/*
402 * Return the total size in bytes
403 */
Paul Bakker23986e52011-04-24 08:57:21 +0000404size_t mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000405{
406 return( ( mpi_msb( X ) + 7 ) >> 3 );
407}
408
409/*
410 * Convert an ASCII character to digit value
411 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000412static int mpi_get_digit( t_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000413{
414 *d = 255;
415
416 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
417 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
418 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
419
Paul Bakkera755ca12011-04-24 09:11:17 +0000420 if( *d >= (t_uint) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000421 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000422
423 return( 0 );
424}
425
426/*
427 * Import from an ASCII string
428 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000429int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000430{
Paul Bakker23986e52011-04-24 08:57:21 +0000431 int ret;
432 size_t i, j, slen, n;
Paul Bakkera755ca12011-04-24 09:11:17 +0000433 t_uint d;
Paul Bakker5121ce52009-01-03 21:22:43 +0000434 mpi T;
435
436 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000437 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000438
Paul Bakker6c591fa2011-05-05 11:49:20 +0000439 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000440
Paul Bakkerff60ee62010-03-16 21:09:09 +0000441 slen = strlen( s );
442
Paul Bakker5121ce52009-01-03 21:22:43 +0000443 if( radix == 16 )
444 {
Manuel Pégourié-Gonnardfa647a72015-10-05 15:23:11 +0100445 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard59efb6a2015-09-28 13:48:04 +0200446 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
447
Paul Bakkerff60ee62010-03-16 21:09:09 +0000448 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000449
450 MPI_CHK( mpi_grow( X, n ) );
451 MPI_CHK( mpi_lset( X, 0 ) );
452
Paul Bakker23986e52011-04-24 08:57:21 +0000453 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000454 {
Paul Bakker23986e52011-04-24 08:57:21 +0000455 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000456 {
457 X->s = -1;
458 break;
459 }
460
Paul Bakker23986e52011-04-24 08:57:21 +0000461 MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200462 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000463 }
464 }
465 else
466 {
467 MPI_CHK( mpi_lset( X, 0 ) );
468
Paul Bakkerff60ee62010-03-16 21:09:09 +0000469 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000470 {
471 if( i == 0 && s[i] == '-' )
472 {
473 X->s = -1;
474 continue;
475 }
476
477 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
478 MPI_CHK( mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000479
480 if( X->s == 1 )
481 {
482 MPI_CHK( mpi_add_int( X, &T, d ) );
483 }
484 else
485 {
486 MPI_CHK( mpi_sub_int( X, &T, d ) );
487 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000488 }
489 }
490
491cleanup:
492
Paul Bakker6c591fa2011-05-05 11:49:20 +0000493 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494
495 return( ret );
496}
497
498/*
499 * Helper to write the digits high-order first
500 */
501static int mpi_write_hlp( mpi *X, int radix, char **p )
502{
503 int ret;
Paul Bakkera755ca12011-04-24 09:11:17 +0000504 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000505
506 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000507 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000508
509 MPI_CHK( mpi_mod_int( &r, X, radix ) );
510 MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
511
512 if( mpi_cmp_int( X, 0 ) != 0 )
513 MPI_CHK( mpi_write_hlp( X, radix, p ) );
514
515 if( r < 10 )
516 *(*p)++ = (char)( r + 0x30 );
517 else
518 *(*p)++ = (char)( r + 0x37 );
519
520cleanup:
521
522 return( ret );
523}
524
525/*
526 * Export into an ASCII string
527 */
Paul Bakker23986e52011-04-24 08:57:21 +0000528int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000529{
Paul Bakker23986e52011-04-24 08:57:21 +0000530 int ret = 0;
531 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000532 char *p;
533 mpi T;
534
535 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000536 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000537
538 n = mpi_msb( X );
539 if( radix >= 4 ) n >>= 1;
540 if( radix >= 16 ) n >>= 1;
541 n += 3;
542
543 if( *slen < n )
544 {
545 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000546 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000547 }
548
549 p = s;
Paul Bakker6c591fa2011-05-05 11:49:20 +0000550 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000551
552 if( X->s == -1 )
553 *p++ = '-';
554
555 if( radix == 16 )
556 {
Paul Bakker23986e52011-04-24 08:57:21 +0000557 int c;
558 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000559
Paul Bakker23986e52011-04-24 08:57:21 +0000560 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000561 {
Paul Bakker23986e52011-04-24 08:57:21 +0000562 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000563 {
Paul Bakker23986e52011-04-24 08:57:21 +0000564 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000565
Paul Bakker6c343d72014-07-10 14:36:19 +0200566 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000567 continue;
568
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000569 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000570 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000571 k = 1;
572 }
573 }
574 }
575 else
576 {
577 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000578
579 if( T.s == -1 )
580 T.s = 1;
581
Paul Bakker5121ce52009-01-03 21:22:43 +0000582 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
583 }
584
585 *p++ = '\0';
586 *slen = p - s;
587
588cleanup:
589
Paul Bakker6c591fa2011-05-05 11:49:20 +0000590 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000591
592 return( ret );
593}
594
Paul Bakker335db3f2011-04-25 15:28:35 +0000595#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000596/*
597 * Read X from an opened file
598 */
599int mpi_read_file( mpi *X, int radix, FILE *fin )
600{
Paul Bakkera755ca12011-04-24 09:11:17 +0000601 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000602 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000603 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000604 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000605 * Buffer should have space for (short) label and decimal formatted MPI,
606 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000607 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000608 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000609
610 memset( s, 0, sizeof( s ) );
611 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000612 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000613
614 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000615 if( slen == sizeof( s ) - 2 )
616 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
617
Paul Bakker5121ce52009-01-03 21:22:43 +0000618 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
619 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
620
621 p = s + slen;
622 while( --p >= s )
623 if( mpi_get_digit( &d, radix, *p ) != 0 )
624 break;
625
626 return( mpi_read_string( X, radix, p + 1 ) );
627}
628
629/*
630 * Write X into an opened file (or stdout if fout == NULL)
631 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000632int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000633{
Paul Bakker23986e52011-04-24 08:57:21 +0000634 int ret;
635 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000636 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000637 * Buffer should have space for (short) label and decimal formatted MPI,
638 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000639 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000640 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000641
642 n = sizeof( s );
643 memset( s, 0, n );
644 n -= 2;
645
Paul Bakker23986e52011-04-24 08:57:21 +0000646 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000647
648 if( p == NULL ) p = "";
649
650 plen = strlen( p );
651 slen = strlen( s );
652 s[slen++] = '\r';
653 s[slen++] = '\n';
654
655 if( fout != NULL )
656 {
657 if( fwrite( p, 1, plen, fout ) != plen ||
658 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000659 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000660 }
661 else
Paul Bakker7dc4c442014-02-01 22:50:26 +0100662 polarssl_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000663
664cleanup:
665
666 return( ret );
667}
Paul Bakker335db3f2011-04-25 15:28:35 +0000668#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000669
670/*
671 * Import X from unsigned binary data, big endian
672 */
Paul Bakker23986e52011-04-24 08:57:21 +0000673int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000674{
Paul Bakker23986e52011-04-24 08:57:21 +0000675 int ret;
676 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000677
678 for( n = 0; n < buflen; n++ )
679 if( buf[n] != 0 )
680 break;
681
682 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
683 MPI_CHK( mpi_lset( X, 0 ) );
684
Paul Bakker23986e52011-04-24 08:57:21 +0000685 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000686 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000687
688cleanup:
689
690 return( ret );
691}
692
693/*
694 * Export X into unsigned binary data, big endian
695 */
Paul Bakker23986e52011-04-24 08:57:21 +0000696int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000697{
Paul Bakker23986e52011-04-24 08:57:21 +0000698 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000699
700 n = mpi_size( X );
701
702 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000703 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000704
705 memset( buf, 0, buflen );
706
707 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
708 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
709
710 return( 0 );
711}
712
713/*
714 * Left-shift: X <<= count
715 */
Paul Bakker23986e52011-04-24 08:57:21 +0000716int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000717{
Paul Bakker23986e52011-04-24 08:57:21 +0000718 int ret;
719 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000720 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000721
722 v0 = count / (biL );
723 t1 = count & (biL - 1);
724
725 i = mpi_msb( X ) + count;
726
Paul Bakkerf9688572011-05-05 10:00:45 +0000727 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000728 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
729
730 ret = 0;
731
732 /*
733 * shift by count / limb_size
734 */
735 if( v0 > 0 )
736 {
Paul Bakker23986e52011-04-24 08:57:21 +0000737 for( i = X->n; i > v0; i-- )
738 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000739
Paul Bakker23986e52011-04-24 08:57:21 +0000740 for( ; i > 0; i-- )
741 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000742 }
743
744 /*
745 * shift by count % limb_size
746 */
747 if( t1 > 0 )
748 {
749 for( i = v0; i < X->n; i++ )
750 {
751 r1 = X->p[i] >> (biL - t1);
752 X->p[i] <<= t1;
753 X->p[i] |= r0;
754 r0 = r1;
755 }
756 }
757
758cleanup:
759
760 return( ret );
761}
762
763/*
764 * Right-shift: X >>= count
765 */
Paul Bakker23986e52011-04-24 08:57:21 +0000766int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000767{
Paul Bakker23986e52011-04-24 08:57:21 +0000768 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000769 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000770
771 v0 = count / biL;
772 v1 = count & (biL - 1);
773
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100774 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
775 return mpi_lset( X, 0 );
776
Paul Bakker5121ce52009-01-03 21:22:43 +0000777 /*
778 * shift by count / limb_size
779 */
780 if( v0 > 0 )
781 {
782 for( i = 0; i < X->n - v0; i++ )
783 X->p[i] = X->p[i + v0];
784
785 for( ; i < X->n; i++ )
786 X->p[i] = 0;
787 }
788
789 /*
790 * shift by count % limb_size
791 */
792 if( v1 > 0 )
793 {
Paul Bakker23986e52011-04-24 08:57:21 +0000794 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000795 {
Paul Bakker23986e52011-04-24 08:57:21 +0000796 r1 = X->p[i - 1] << (biL - v1);
797 X->p[i - 1] >>= v1;
798 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000799 r0 = r1;
800 }
801 }
802
803 return( 0 );
804}
805
806/*
807 * Compare unsigned values
808 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000809int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000810{
Paul Bakker23986e52011-04-24 08:57:21 +0000811 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000812
Paul Bakker23986e52011-04-24 08:57:21 +0000813 for( i = X->n; i > 0; i-- )
814 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000815 break;
816
Paul Bakker23986e52011-04-24 08:57:21 +0000817 for( j = Y->n; j > 0; j-- )
818 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000819 break;
820
Paul Bakker23986e52011-04-24 08:57:21 +0000821 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000822 return( 0 );
823
824 if( i > j ) return( 1 );
825 if( j > i ) return( -1 );
826
Paul Bakker23986e52011-04-24 08:57:21 +0000827 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000828 {
Paul Bakker23986e52011-04-24 08:57:21 +0000829 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
830 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000831 }
832
833 return( 0 );
834}
835
836/*
837 * Compare signed values
838 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000839int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000840{
Paul Bakker23986e52011-04-24 08:57:21 +0000841 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000842
Paul Bakker23986e52011-04-24 08:57:21 +0000843 for( i = X->n; i > 0; i-- )
844 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000845 break;
846
Paul Bakker23986e52011-04-24 08:57:21 +0000847 for( j = Y->n; j > 0; j-- )
848 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000849 break;
850
Paul Bakker23986e52011-04-24 08:57:21 +0000851 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000852 return( 0 );
853
854 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000855 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000856
857 if( X->s > 0 && Y->s < 0 ) return( 1 );
858 if( Y->s > 0 && X->s < 0 ) return( -1 );
859
Paul Bakker23986e52011-04-24 08:57:21 +0000860 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000861 {
Paul Bakker23986e52011-04-24 08:57:21 +0000862 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
863 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000864 }
865
866 return( 0 );
867}
868
869/*
870 * Compare signed values
871 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000872int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000873{
874 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000875 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000876
877 *p = ( z < 0 ) ? -z : z;
878 Y.s = ( z < 0 ) ? -1 : 1;
879 Y.n = 1;
880 Y.p = p;
881
882 return( mpi_cmp_mpi( X, &Y ) );
883}
884
885/*
886 * Unsigned addition: X = |A| + |B| (HAC 14.7)
887 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000888int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000889{
Paul Bakker23986e52011-04-24 08:57:21 +0000890 int ret;
891 size_t i, j;
Janos Follath2db440d2015-10-30 17:43:11 +0100892 mpi_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:
Janos Follath2db440d2015-10-30 17:43:11 +0100937<<<<<<< HEAD
Janos Follath2b806fa2015-10-25 14:24:10 +0100938 if( &TB == B )
939 {
940 mpi_free( &TB );
941 }
Janos Follath2db440d2015-10-30 17:43:11 +0100942=======
943>>>>>>> 6c9226809370... Improved on the previous fix and added a test case to cover both types
Paul Bakker5121ce52009-01-03 21:22:43 +0000944
945 return( ret );
946}
947
948/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100949 * Helper for mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000950 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000951static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000952{
Paul Bakker23986e52011-04-24 08:57:21 +0000953 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000954 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000955
956 for( i = c = 0; i < n; i++, s++, d++ )
957 {
958 z = ( *d < c ); *d -= c;
959 c = ( *d < *s ) + z; *d -= *s;
960 }
961
962 while( c != 0 )
963 {
964 z = ( *d < c ); *d -= c;
965 c = z; i++; d++;
966 }
967}
968
969/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100970 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000971 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000972int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000973{
974 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000975 int ret;
976 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000977
978 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000979 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000980
Paul Bakker6c591fa2011-05-05 11:49:20 +0000981 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000982
983 if( X == B )
984 {
985 MPI_CHK( mpi_copy( &TB, B ) );
986 B = &TB;
987 }
988
989 if( X != A )
990 MPI_CHK( mpi_copy( X, A ) );
991
Paul Bakker1ef7a532009-06-20 10:50:55 +0000992 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100993 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000994 */
995 X->s = 1;
996
Paul Bakker5121ce52009-01-03 21:22:43 +0000997 ret = 0;
998
Paul Bakker23986e52011-04-24 08:57:21 +0000999 for( n = B->n; n > 0; n-- )
1000 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001001 break;
1002
Paul Bakker23986e52011-04-24 08:57:21 +00001003 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001004
1005cleanup:
1006
Paul Bakker6c591fa2011-05-05 11:49:20 +00001007 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001008
1009 return( ret );
1010}
1011
1012/*
1013 * Signed addition: X = A + B
1014 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001015int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001016{
1017 int ret, s = A->s;
1018
1019 if( A->s * B->s < 0 )
1020 {
1021 if( mpi_cmp_abs( A, B ) >= 0 )
1022 {
1023 MPI_CHK( mpi_sub_abs( X, A, B ) );
1024 X->s = s;
1025 }
1026 else
1027 {
1028 MPI_CHK( mpi_sub_abs( X, B, A ) );
1029 X->s = -s;
1030 }
1031 }
1032 else
1033 {
1034 MPI_CHK( mpi_add_abs( X, A, B ) );
1035 X->s = s;
1036 }
1037
1038cleanup:
1039
1040 return( ret );
1041}
1042
1043/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001044 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001045 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001046int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001047{
1048 int ret, s = A->s;
1049
1050 if( A->s * B->s > 0 )
1051 {
1052 if( mpi_cmp_abs( A, B ) >= 0 )
1053 {
1054 MPI_CHK( mpi_sub_abs( X, A, B ) );
1055 X->s = s;
1056 }
1057 else
1058 {
1059 MPI_CHK( mpi_sub_abs( X, B, A ) );
1060 X->s = -s;
1061 }
1062 }
1063 else
1064 {
1065 MPI_CHK( mpi_add_abs( X, A, B ) );
1066 X->s = s;
1067 }
1068
1069cleanup:
1070
1071 return( ret );
1072}
1073
1074/*
1075 * Signed addition: X = A + b
1076 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001077int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001078{
1079 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001080 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001081
1082 p[0] = ( b < 0 ) ? -b : b;
1083 _B.s = ( b < 0 ) ? -1 : 1;
1084 _B.n = 1;
1085 _B.p = p;
1086
1087 return( mpi_add_mpi( X, A, &_B ) );
1088}
1089
1090/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001091 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001092 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001093int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001094{
1095 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001096 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001097
1098 p[0] = ( b < 0 ) ? -b : b;
1099 _B.s = ( b < 0 ) ? -1 : 1;
1100 _B.n = 1;
1101 _B.p = p;
1102
1103 return( mpi_sub_mpi( X, A, &_B ) );
1104}
1105
1106/*
1107 * Helper for mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001108 */
1109static
1110#if defined(__APPLE__) && defined(__arm__)
1111/*
1112 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1113 * appears to need this to prevent bad ARM code generation at -O3.
1114 */
1115__attribute__ ((noinline))
1116#endif
1117void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001118{
Paul Bakkera755ca12011-04-24 09:11:17 +00001119 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001120
1121#if defined(MULADDC_HUIT)
1122 for( ; i >= 8; i -= 8 )
1123 {
1124 MULADDC_INIT
1125 MULADDC_HUIT
1126 MULADDC_STOP
1127 }
1128
1129 for( ; i > 0; i-- )
1130 {
1131 MULADDC_INIT
1132 MULADDC_CORE
1133 MULADDC_STOP
1134 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001135#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001136 for( ; i >= 16; i -= 16 )
1137 {
1138 MULADDC_INIT
1139 MULADDC_CORE MULADDC_CORE
1140 MULADDC_CORE MULADDC_CORE
1141 MULADDC_CORE MULADDC_CORE
1142 MULADDC_CORE MULADDC_CORE
1143
1144 MULADDC_CORE MULADDC_CORE
1145 MULADDC_CORE MULADDC_CORE
1146 MULADDC_CORE MULADDC_CORE
1147 MULADDC_CORE MULADDC_CORE
1148 MULADDC_STOP
1149 }
1150
1151 for( ; i >= 8; i -= 8 )
1152 {
1153 MULADDC_INIT
1154 MULADDC_CORE MULADDC_CORE
1155 MULADDC_CORE MULADDC_CORE
1156
1157 MULADDC_CORE MULADDC_CORE
1158 MULADDC_CORE MULADDC_CORE
1159 MULADDC_STOP
1160 }
1161
1162 for( ; i > 0; i-- )
1163 {
1164 MULADDC_INIT
1165 MULADDC_CORE
1166 MULADDC_STOP
1167 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001168#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001169
1170 t++;
1171
1172 do {
1173 *d += c; c = ( *d < c ); d++;
1174 }
1175 while( c != 0 );
1176}
1177
1178/*
1179 * Baseline multiplication: X = A * B (HAC 14.12)
1180 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001181int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001182{
Paul Bakker23986e52011-04-24 08:57:21 +00001183 int ret;
1184 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001185 mpi TA, TB;
1186
Paul Bakker6c591fa2011-05-05 11:49:20 +00001187 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001188
1189 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1190 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1191
Paul Bakker23986e52011-04-24 08:57:21 +00001192 for( i = A->n; i > 0; i-- )
1193 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001194 break;
1195
Paul Bakker23986e52011-04-24 08:57:21 +00001196 for( j = B->n; j > 0; j-- )
1197 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001198 break;
1199
Paul Bakker23986e52011-04-24 08:57:21 +00001200 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001201 MPI_CHK( mpi_lset( X, 0 ) );
1202
Paul Bakker23986e52011-04-24 08:57:21 +00001203 for( i++; j > 0; j-- )
1204 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001205
1206 X->s = A->s * B->s;
1207
1208cleanup:
1209
Paul Bakker6c591fa2011-05-05 11:49:20 +00001210 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001211
1212 return( ret );
1213}
1214
1215/*
1216 * Baseline multiplication: X = A * b
1217 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001218int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001219{
1220 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001221 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001222
1223 _B.s = 1;
1224 _B.n = 1;
1225 _B.p = p;
1226 p[0] = b;
1227
1228 return( mpi_mul_mpi( X, A, &_B ) );
1229}
1230
1231/*
Simon Butcher14400c82016-01-02 00:08:13 +00001232 * Unsigned integer divide - double t_uint, dividend, u1/u0, and t_uint
1233 * divisor, d
Simon Butchere4ed3472015-12-22 15:26:57 +00001234 */
Simon Butcher14400c82016-01-02 00:08:13 +00001235static t_uint int_div_int( t_uint u1, t_uint u0, t_uint d, t_uint *r )
Simon Butchere4ed3472015-12-22 15:26:57 +00001236{
1237#if defined(POLARSSL_HAVE_UDBL)
1238 t_udbl dividend, quotient;
Simon Butcher14400c82016-01-02 00:08:13 +00001239#else
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001240 const t_uint radix = (t_uint) 1 << biH;
1241 const t_uint uint_halfword_mask = ( (t_uint) 1 << biH ) - 1;
Simon Butcher14400c82016-01-02 00:08:13 +00001242 t_uint d0, d1, q0, q1, rAX, r0, quotient;
1243 t_uint u0_msw, u0_lsw;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001244 size_t s;
Simon Butchere4ed3472015-12-22 15:26:57 +00001245#endif
1246
1247 /*
1248 * Check for overflow
1249 */
Simon Butcher14400c82016-01-02 00:08:13 +00001250 if( 0 == d || u1 >= d )
Simon Butchere4ed3472015-12-22 15:26:57 +00001251 {
Simon Butcher14400c82016-01-02 00:08:13 +00001252 if ( r != NULL ) *r = ~0;
Simon Butchere4ed3472015-12-22 15:26:57 +00001253
Simon Butcher14400c82016-01-02 00:08:13 +00001254 return ( ~0 );
Simon Butchere4ed3472015-12-22 15:26:57 +00001255 }
1256
1257#if defined(POLARSSL_HAVE_UDBL)
1258 dividend = (t_udbl) u1 << biL;
1259 dividend |= (t_udbl) u0;
1260 quotient = dividend / d;
1261 if( quotient > ( (t_udbl) 1 << biL ) - 1 )
1262 quotient = ( (t_udbl) 1 << biL ) - 1;
1263
1264 if( r != NULL )
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001265 *r = (t_uint)( dividend - (quotient * d ) );
Simon Butchere4ed3472015-12-22 15:26:57 +00001266
1267 return (t_uint) quotient;
1268#else
Simon Butchere4ed3472015-12-22 15:26:57 +00001269
1270 /*
1271 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1272 * Vol. 2 - Seminumerical Algorithms, Knuth
1273 */
1274
1275 /*
1276 * Normalize the divisor, d, and dividend, u0, u1
1277 */
1278 s = int_clz( d );
1279 d = d << s;
1280
1281 u1 = u1 << s;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001282 u1 |= ( u0 >> ( biL - s ) ) & ( -(t_sint)s >> ( biL - 1 ) );
Simon Butchere4ed3472015-12-22 15:26:57 +00001283 u0 = u0 << s;
1284
1285 d1 = d >> biH;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001286 d0 = d & uint_halfword_mask;
Simon Butchere4ed3472015-12-22 15:26:57 +00001287
1288 u0_msw = u0 >> biH;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001289 u0_lsw = u0 & uint_halfword_mask;
Simon Butchere4ed3472015-12-22 15:26:57 +00001290
1291 /*
1292 * Find the first quotient and remainder
1293 */
1294 q1 = u1 / d1;
1295 r0 = u1 - d1 * q1;
1296
1297 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1298 {
1299 q1 -= 1;
1300 r0 += d1;
1301
1302 if ( r0 >= radix ) break;
1303 }
1304
Simon Butcher14400c82016-01-02 00:08:13 +00001305 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butchere4ed3472015-12-22 15:26:57 +00001306 q0 = rAX / d1;
1307 r0 = rAX - q0 * d1;
1308
1309 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1310 {
1311 q0 -= 1;
1312 r0 += d1;
1313
1314 if ( r0 >= radix ) break;
1315 }
1316
1317 if (r != NULL)
Simon Butcher14400c82016-01-02 00:08:13 +00001318 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butchere4ed3472015-12-22 15:26:57 +00001319
1320 quotient = q1 * radix + q0;
1321
1322 return quotient;
1323#endif
1324}
1325
1326/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001327 * Division by mpi: A = Q * B + R (HAC 14.20)
1328 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001329int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001330{
Paul Bakker23986e52011-04-24 08:57:21 +00001331 int ret;
1332 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001333 mpi X, Y, Z, T1, T2;
1334
1335 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001336 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001337
Paul Bakker6c591fa2011-05-05 11:49:20 +00001338 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1339 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001340
1341 if( mpi_cmp_abs( A, B ) < 0 )
1342 {
1343 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1344 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1345 return( 0 );
1346 }
1347
1348 MPI_CHK( mpi_copy( &X, A ) );
1349 MPI_CHK( mpi_copy( &Y, B ) );
1350 X.s = Y.s = 1;
1351
1352 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1353 MPI_CHK( mpi_lset( &Z, 0 ) );
1354 MPI_CHK( mpi_grow( &T1, 2 ) );
1355 MPI_CHK( mpi_grow( &T2, 3 ) );
1356
1357 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001358 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001359 {
1360 k = biL - 1 - k;
1361 MPI_CHK( mpi_shift_l( &X, k ) );
1362 MPI_CHK( mpi_shift_l( &Y, k ) );
1363 }
1364 else k = 0;
1365
1366 n = X.n - 1;
1367 t = Y.n - 1;
Paul Bakker66d5d072014-06-17 16:39:18 +02001368 MPI_CHK( mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001369
1370 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1371 {
1372 Z.p[n - t]++;
Paul Bakker6ea1a952013-12-31 11:16:03 +01001373 MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001374 }
Paul Bakker66d5d072014-06-17 16:39:18 +02001375 MPI_CHK( mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001376
1377 for( i = n; i > t ; i-- )
1378 {
1379 if( X.p[i] >= Y.p[t] )
1380 Z.p[i - t - 1] = ~0;
1381 else
1382 {
Simon Butchere4ed3472015-12-22 15:26:57 +00001383 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 +00001384 }
1385
1386 Z.p[i - t - 1]++;
1387 do
1388 {
1389 Z.p[i - t - 1]--;
1390
1391 MPI_CHK( mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001392 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001393 T1.p[1] = Y.p[t];
1394 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1395
1396 MPI_CHK( mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001397 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1398 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001399 T2.p[2] = X.p[i];
1400 }
1401 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1402
1403 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
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_sub_mpi( &X, &X, &T1 ) );
1406
1407 if( mpi_cmp_int( &X, 0 ) < 0 )
1408 {
1409 MPI_CHK( mpi_copy( &T1, &Y ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001410 MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001411 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1412 Z.p[i - t - 1]--;
1413 }
1414 }
1415
1416 if( Q != NULL )
1417 {
Paul Bakker6ea1a952013-12-31 11:16:03 +01001418 MPI_CHK( mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001419 Q->s = A->s * B->s;
1420 }
1421
1422 if( R != NULL )
1423 {
Paul Bakker6ea1a952013-12-31 11:16:03 +01001424 MPI_CHK( mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001425 X.s = A->s;
Paul Bakker6ea1a952013-12-31 11:16:03 +01001426 MPI_CHK( mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001427
Paul Bakker5121ce52009-01-03 21:22:43 +00001428 if( mpi_cmp_int( R, 0 ) == 0 )
1429 R->s = 1;
1430 }
1431
1432cleanup:
1433
Paul Bakker6c591fa2011-05-05 11:49:20 +00001434 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1435 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001436
1437 return( ret );
1438}
1439
1440/*
1441 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001442 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001443int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001444{
1445 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001446 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001447
1448 p[0] = ( b < 0 ) ? -b : b;
1449 _B.s = ( b < 0 ) ? -1 : 1;
1450 _B.n = 1;
1451 _B.p = p;
1452
1453 return( mpi_div_mpi( Q, R, A, &_B ) );
1454}
1455
1456/*
1457 * Modulo: R = A mod B
1458 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001459int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001460{
1461 int ret;
1462
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001463 if( mpi_cmp_int( B, 0 ) < 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001464 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001465
Paul Bakker5121ce52009-01-03 21:22:43 +00001466 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1467
1468 while( mpi_cmp_int( R, 0 ) < 0 )
1469 MPI_CHK( mpi_add_mpi( R, R, B ) );
1470
1471 while( mpi_cmp_mpi( R, B ) >= 0 )
1472 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1473
1474cleanup:
1475
1476 return( ret );
1477}
1478
1479/*
1480 * Modulo: r = A mod b
1481 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001482int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001483{
Paul Bakker23986e52011-04-24 08:57:21 +00001484 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001485 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001486
1487 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001488 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001489
1490 if( b < 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001491 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001492
1493 /*
1494 * handle trivial cases
1495 */
1496 if( b == 1 )
1497 {
1498 *r = 0;
1499 return( 0 );
1500 }
1501
1502 if( b == 2 )
1503 {
1504 *r = A->p[0] & 1;
1505 return( 0 );
1506 }
1507
1508 /*
1509 * general case
1510 */
Paul Bakker23986e52011-04-24 08:57:21 +00001511 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001512 {
Paul Bakker23986e52011-04-24 08:57:21 +00001513 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001514 y = ( y << biH ) | ( x >> biH );
1515 z = y / b;
1516 y -= z * b;
1517
1518 x <<= biH;
1519 y = ( y << biH ) | ( x >> biH );
1520 z = y / b;
1521 y -= z * b;
1522 }
1523
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001524 /*
1525 * If A is negative, then the current y represents a negative value.
1526 * Flipping it to the positive side.
1527 */
1528 if( A->s < 0 && y != 0 )
1529 y = b - y;
1530
Paul Bakker5121ce52009-01-03 21:22:43 +00001531 *r = y;
1532
1533 return( 0 );
1534}
1535
1536/*
1537 * Fast Montgomery initialization (thanks to Tom St Denis)
1538 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001539static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001540{
Paul Bakkera755ca12011-04-24 09:11:17 +00001541 t_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001542 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001543
1544 x = m0;
1545 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001546
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001547 for( i = biL; i >= 8; i /= 2 )
1548 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001549
1550 *mm = ~x + 1;
1551}
1552
1553/*
1554 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1555 */
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02001556static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm,
1557 const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001558{
Paul Bakker23986e52011-04-24 08:57:21 +00001559 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001560 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001561
1562 memset( T->p, 0, T->n * ciL );
1563
1564 d = T->p;
1565 n = N->n;
1566 m = ( B->n < n ) ? B->n : n;
1567
1568 for( i = 0; i < n; i++ )
1569 {
1570 /*
1571 * T = (T + u0*B + u1*N) / 2^biL
1572 */
1573 u0 = A->p[i];
1574 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1575
1576 mpi_mul_hlp( m, B->p, d, u0 );
1577 mpi_mul_hlp( n, N->p, d, u1 );
1578
1579 *d++ = u0; d[n + 1] = 0;
1580 }
1581
Paul Bakker66d5d072014-06-17 16:39:18 +02001582 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001583
1584 if( mpi_cmp_abs( A, N ) >= 0 )
1585 mpi_sub_hlp( n, N->p, A->p );
1586 else
1587 /* prevent timing attacks */
1588 mpi_sub_hlp( n, A->p, T->p );
1589}
1590
1591/*
1592 * Montgomery reduction: A = A * R^-1 mod N
1593 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001594static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001595{
Paul Bakkera755ca12011-04-24 09:11:17 +00001596 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001597 mpi U;
1598
Paul Bakker8ddb6452013-02-27 14:56:33 +01001599 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001600 U.p = &z;
1601
1602 mpi_montmul( A, &U, N, mm, T );
1603}
1604
1605/*
1606 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1607 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001608int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001609{
Paul Bakker23986e52011-04-24 08:57:21 +00001610 int ret;
1611 size_t wbits, wsize, one = 1;
1612 size_t i, j, nblimbs;
1613 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001614 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001615 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1616 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001617
1618 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001619 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001620
Paul Bakkerf6198c12012-05-16 08:02:29 +00001621 if( mpi_cmp_int( E, 0 ) < 0 )
1622 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1623
1624 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001625 * Init temps and window size
1626 */
1627 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001628 mpi_init( &RR ); mpi_init( &T );
Manuel Pégourié-Gonnardfd6a1912014-01-18 19:05:23 +01001629 mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001630 memset( W, 0, sizeof( W ) );
1631
1632 i = mpi_msb( E );
1633
1634 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1635 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1636
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001637 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1638 wsize = POLARSSL_MPI_WINDOW_SIZE;
1639
Paul Bakker5121ce52009-01-03 21:22:43 +00001640 j = N->n + 1;
1641 MPI_CHK( mpi_grow( X, j ) );
1642 MPI_CHK( mpi_grow( &W[1], j ) );
1643 MPI_CHK( mpi_grow( &T, j * 2 ) );
1644
1645 /*
Paul Bakker50546922012-05-19 08:40:49 +00001646 * Compensate for negative A (and correct at the end)
1647 */
1648 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001649 if( neg )
1650 {
1651 MPI_CHK( mpi_copy( &Apos, A ) );
1652 Apos.s = 1;
1653 A = &Apos;
1654 }
1655
1656 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001657 * If 1st call, pre-compute R^2 mod N
1658 */
1659 if( _RR == NULL || _RR->p == NULL )
1660 {
1661 MPI_CHK( mpi_lset( &RR, 1 ) );
1662 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1663 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1664
1665 if( _RR != NULL )
1666 memcpy( _RR, &RR, sizeof( mpi ) );
1667 }
1668 else
1669 memcpy( &RR, _RR, sizeof( mpi ) );
1670
1671 /*
1672 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1673 */
1674 if( mpi_cmp_mpi( A, N ) >= 0 )
Paul Bakkerc2024f42014-01-23 20:38:35 +01001675 MPI_CHK( mpi_mod_mpi( &W[1], A, N ) );
1676 else
1677 MPI_CHK( mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001678
1679 mpi_montmul( &W[1], &RR, N, mm, &T );
1680
1681 /*
1682 * X = R^2 * R^-1 mod N = R mod N
1683 */
1684 MPI_CHK( mpi_copy( X, &RR ) );
1685 mpi_montred( X, N, mm, &T );
1686
1687 if( wsize > 1 )
1688 {
1689 /*
1690 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1691 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001692 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001693
1694 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1695 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1696
1697 for( i = 0; i < wsize - 1; i++ )
1698 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001699
Paul Bakker5121ce52009-01-03 21:22:43 +00001700 /*
1701 * W[i] = W[i - 1] * W[1]
1702 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001703 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001704 {
1705 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1706 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1707
1708 mpi_montmul( &W[i], &W[1], N, mm, &T );
1709 }
1710 }
1711
1712 nblimbs = E->n;
1713 bufsize = 0;
1714 nbits = 0;
1715 wbits = 0;
1716 state = 0;
1717
1718 while( 1 )
1719 {
1720 if( bufsize == 0 )
1721 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001722 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001723 break;
1724
Paul Bakker0d7702c2013-10-29 16:18:35 +01001725 nblimbs--;
1726
Paul Bakkera755ca12011-04-24 09:11:17 +00001727 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001728 }
1729
1730 bufsize--;
1731
1732 ei = (E->p[nblimbs] >> bufsize) & 1;
1733
1734 /*
1735 * skip leading 0s
1736 */
1737 if( ei == 0 && state == 0 )
1738 continue;
1739
1740 if( ei == 0 && state == 1 )
1741 {
1742 /*
1743 * out of window, square X
1744 */
1745 mpi_montmul( X, X, N, mm, &T );
1746 continue;
1747 }
1748
1749 /*
1750 * add ei to current window
1751 */
1752 state = 2;
1753
1754 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001755 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001756
1757 if( nbits == wsize )
1758 {
1759 /*
1760 * X = X^wsize R^-1 mod N
1761 */
1762 for( i = 0; i < wsize; i++ )
1763 mpi_montmul( X, X, N, mm, &T );
1764
1765 /*
1766 * X = X * W[wbits] R^-1 mod N
1767 */
1768 mpi_montmul( X, &W[wbits], N, mm, &T );
1769
1770 state--;
1771 nbits = 0;
1772 wbits = 0;
1773 }
1774 }
1775
1776 /*
1777 * process the remaining bits
1778 */
1779 for( i = 0; i < nbits; i++ )
1780 {
1781 mpi_montmul( X, X, N, mm, &T );
1782
1783 wbits <<= 1;
1784
Paul Bakker66d5d072014-06-17 16:39:18 +02001785 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001786 mpi_montmul( X, &W[1], N, mm, &T );
1787 }
1788
1789 /*
1790 * X = A^E * R * R^-1 mod N = A^E mod N
1791 */
1792 mpi_montred( X, N, mm, &T );
1793
Paul Bakkerf6198c12012-05-16 08:02:29 +00001794 if( neg )
1795 {
1796 X->s = -1;
Paul Bakkerc2024f42014-01-23 20:38:35 +01001797 MPI_CHK( mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001798 }
1799
Paul Bakker5121ce52009-01-03 21:22:43 +00001800cleanup:
1801
Paul Bakker66d5d072014-06-17 16:39:18 +02001802 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001803 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001804
Paul Bakkerf6198c12012-05-16 08:02:29 +00001805 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001806
Paul Bakker75a28602014-03-31 12:08:17 +02001807 if( _RR == NULL || _RR->p == NULL )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001808 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001809
1810 return( ret );
1811}
1812
Paul Bakker5121ce52009-01-03 21:22:43 +00001813/*
1814 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1815 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001816int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001817{
Paul Bakker23986e52011-04-24 08:57:21 +00001818 int ret;
1819 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001820 mpi TG, TA, TB;
1821
Paul Bakker6c591fa2011-05-05 11:49:20 +00001822 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001823
Paul Bakker5121ce52009-01-03 21:22:43 +00001824 MPI_CHK( mpi_copy( &TA, A ) );
1825 MPI_CHK( mpi_copy( &TB, B ) );
1826
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001827 lz = mpi_lsb( &TA );
1828 lzt = mpi_lsb( &TB );
1829
Paul Bakker66d5d072014-06-17 16:39:18 +02001830 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001831 lz = lzt;
1832
1833 MPI_CHK( mpi_shift_r( &TA, lz ) );
1834 MPI_CHK( mpi_shift_r( &TB, lz ) );
1835
Paul Bakker5121ce52009-01-03 21:22:43 +00001836 TA.s = TB.s = 1;
1837
1838 while( mpi_cmp_int( &TA, 0 ) != 0 )
1839 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001840 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1841 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001842
1843 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1844 {
1845 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1846 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1847 }
1848 else
1849 {
1850 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1851 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1852 }
1853 }
1854
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001855 MPI_CHK( mpi_shift_l( &TB, lz ) );
1856 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001857
1858cleanup:
1859
Paul Bakker6c591fa2011-05-05 11:49:20 +00001860 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001861
1862 return( ret );
1863}
1864
Paul Bakker33dc46b2014-04-30 16:11:39 +02001865/*
1866 * Fill X with size bytes of random.
1867 *
1868 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001869 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001870 * deterministic, eg for tests).
1871 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001872int mpi_fill_random( mpi *X, size_t size,
1873 int (*f_rng)(void *, unsigned char *, size_t),
1874 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001875{
Paul Bakker23986e52011-04-24 08:57:21 +00001876 int ret;
Paul Bakker33dc46b2014-04-30 16:11:39 +02001877 unsigned char buf[POLARSSL_MPI_MAX_SIZE];
1878
1879 if( size > POLARSSL_MPI_MAX_SIZE )
1880 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001881
Paul Bakker33dc46b2014-04-30 16:11:39 +02001882 MPI_CHK( f_rng( p_rng, buf, size ) );
1883 MPI_CHK( mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001884
1885cleanup:
1886 return( ret );
1887}
1888
Paul Bakker5121ce52009-01-03 21:22:43 +00001889/*
1890 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1891 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001892int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001893{
1894 int ret;
1895 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1896
1897 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001898 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001899
Paul Bakker6c591fa2011-05-05 11:49:20 +00001900 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1901 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1902 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001903
1904 MPI_CHK( mpi_gcd( &G, A, N ) );
1905
1906 if( mpi_cmp_int( &G, 1 ) != 0 )
1907 {
Paul Bakker40e46942009-01-03 21:51:57 +00001908 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001909 goto cleanup;
1910 }
1911
1912 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1913 MPI_CHK( mpi_copy( &TU, &TA ) );
1914 MPI_CHK( mpi_copy( &TB, N ) );
1915 MPI_CHK( mpi_copy( &TV, N ) );
1916
1917 MPI_CHK( mpi_lset( &U1, 1 ) );
1918 MPI_CHK( mpi_lset( &U2, 0 ) );
1919 MPI_CHK( mpi_lset( &V1, 0 ) );
1920 MPI_CHK( mpi_lset( &V2, 1 ) );
1921
1922 do
1923 {
1924 while( ( TU.p[0] & 1 ) == 0 )
1925 {
1926 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1927
1928 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1929 {
1930 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1931 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1932 }
1933
1934 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1935 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1936 }
1937
1938 while( ( TV.p[0] & 1 ) == 0 )
1939 {
1940 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1941
1942 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1943 {
1944 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1945 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1946 }
1947
1948 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1949 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1950 }
1951
1952 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1953 {
1954 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1955 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1956 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1957 }
1958 else
1959 {
1960 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1961 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1962 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1963 }
1964 }
1965 while( mpi_cmp_int( &TU, 0 ) != 0 );
1966
1967 while( mpi_cmp_int( &V1, 0 ) < 0 )
1968 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1969
1970 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1971 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1972
1973 MPI_CHK( mpi_copy( X, &V1 ) );
1974
1975cleanup:
1976
Paul Bakker6c591fa2011-05-05 11:49:20 +00001977 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1978 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1979 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001980
1981 return( ret );
1982}
1983
Paul Bakkerd9374b02012-11-02 11:02:58 +00001984#if defined(POLARSSL_GENPRIME)
1985
Paul Bakker5121ce52009-01-03 21:22:43 +00001986static const int small_prime[] =
1987{
1988 3, 5, 7, 11, 13, 17, 19, 23,
1989 29, 31, 37, 41, 43, 47, 53, 59,
1990 61, 67, 71, 73, 79, 83, 89, 97,
1991 101, 103, 107, 109, 113, 127, 131, 137,
1992 139, 149, 151, 157, 163, 167, 173, 179,
1993 181, 191, 193, 197, 199, 211, 223, 227,
1994 229, 233, 239, 241, 251, 257, 263, 269,
1995 271, 277, 281, 283, 293, 307, 311, 313,
1996 317, 331, 337, 347, 349, 353, 359, 367,
1997 373, 379, 383, 389, 397, 401, 409, 419,
1998 421, 431, 433, 439, 443, 449, 457, 461,
1999 463, 467, 479, 487, 491, 499, 503, 509,
2000 521, 523, 541, 547, 557, 563, 569, 571,
2001 577, 587, 593, 599, 601, 607, 613, 617,
2002 619, 631, 641, 643, 647, 653, 659, 661,
2003 673, 677, 683, 691, 701, 709, 719, 727,
2004 733, 739, 743, 751, 757, 761, 769, 773,
2005 787, 797, 809, 811, 821, 823, 827, 829,
2006 839, 853, 857, 859, 863, 877, 881, 883,
2007 887, 907, 911, 919, 929, 937, 941, 947,
2008 953, 967, 971, 977, 983, 991, 997, -103
2009};
2010
2011/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002012 * Small divisors test (X must be positive)
2013 *
2014 * Return values:
2015 * 0: no small factor (possible prime, more tests needed)
2016 * 1: certain prime
2017 * POLARSSL_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2018 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002019 */
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002020static int mpi_check_small_factors( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002021{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002022 int ret = 0;
2023 size_t i;
2024 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002025
Paul Bakker5121ce52009-01-03 21:22:43 +00002026 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002027 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002028
2029 for( i = 0; small_prime[i] > 0; i++ )
2030 {
Paul Bakker5121ce52009-01-03 21:22:43 +00002031 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002032 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002033
2034 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
2035
2036 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002037 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002038 }
2039
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002040cleanup:
2041 return( ret );
2042}
2043
2044/*
2045 * Miller-Rabin pseudo-primality test (HAC 4.24)
2046 */
2047static int mpi_miller_rabin( const mpi *X,
2048 int (*f_rng)(void *, unsigned char *, size_t),
2049 void *p_rng )
2050{
Pascal Junodb99183d2015-03-11 16:49:45 +01002051 int ret, count;
2052 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002053 mpi W, R, T, A, RR;
2054
2055 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
2056 mpi_init( &RR );
2057
Paul Bakker5121ce52009-01-03 21:22:43 +00002058 /*
2059 * W = |X| - 1
2060 * R = W >> lsb( W )
2061 */
Paul Bakker5121ce52009-01-03 21:22:43 +00002062 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00002063 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00002064 MPI_CHK( mpi_copy( &R, &W ) );
2065 MPI_CHK( mpi_shift_r( &R, s ) );
2066
2067 i = mpi_msb( X );
2068 /*
2069 * HAC, table 4.4
2070 */
2071 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2072 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2073 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2074
2075 for( i = 0; i < n; i++ )
2076 {
2077 /*
2078 * pick a random A, 1 < A < |X| - 1
2079 */
Paul Bakker5121ce52009-01-03 21:22:43 +00002080
Pascal Junodb99183d2015-03-11 16:49:45 +01002081 count = 0;
2082 do {
2083 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
2084
2085 j = mpi_msb( &A );
2086 k = mpi_msb( &W );
2087 if (j > k) {
2088 MPI_CHK( mpi_shift_r( &A, j - k ) );
2089 }
2090
2091 if (count++ > 30) {
2092 return POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
2093 }
2094
2095 } while ( (mpi_cmp_mpi( &A, &W ) >= 0) ||
2096 (mpi_cmp_int( &A, 1 ) <= 0) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002097
2098 /*
2099 * A = A^R mod |X|
2100 */
2101 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
2102
2103 if( mpi_cmp_mpi( &A, &W ) == 0 ||
2104 mpi_cmp_int( &A, 1 ) == 0 )
2105 continue;
2106
2107 j = 1;
2108 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
2109 {
2110 /*
2111 * A = A * A mod |X|
2112 */
2113 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
2114 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
2115
2116 if( mpi_cmp_int( &A, 1 ) == 0 )
2117 break;
2118
2119 j++;
2120 }
2121
2122 /*
2123 * not prime if A != |X| - 1 or A == 1
2124 */
2125 if( mpi_cmp_mpi( &A, &W ) != 0 ||
2126 mpi_cmp_int( &A, 1 ) == 0 )
2127 {
Paul Bakker40e46942009-01-03 21:51:57 +00002128 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002129 break;
2130 }
2131 }
2132
2133cleanup:
Paul Bakker6c591fa2011-05-05 11:49:20 +00002134 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
2135 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002136
2137 return( ret );
2138}
2139
2140/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002141 * Pseudo-primality test: small factors, then Miller-Rabin
2142 */
Paul Bakker45f457d2013-11-25 14:26:52 +01002143int mpi_is_prime( mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002144 int (*f_rng)(void *, unsigned char *, size_t),
2145 void *p_rng )
2146{
2147 int ret;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002148 mpi XX;
2149
2150 XX.s = 1;
2151 XX.n = X->n;
2152 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002153
2154 if( mpi_cmp_int( &XX, 0 ) == 0 ||
2155 mpi_cmp_int( &XX, 1 ) == 0 )
2156 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
2157
2158 if( mpi_cmp_int( &XX, 2 ) == 0 )
2159 return( 0 );
2160
2161 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2162 {
2163 if( ret == 1 )
2164 return( 0 );
2165
2166 return( ret );
2167 }
2168
2169 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2170}
2171
2172/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002173 * Prime number generation
2174 */
Paul Bakker23986e52011-04-24 08:57:21 +00002175int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002176 int (*f_rng)(void *, unsigned char *, size_t),
2177 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002178{
Paul Bakker23986e52011-04-24 08:57:21 +00002179 int ret;
2180 size_t k, n;
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002181 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002182 mpi Y;
2183
Paul Bakkerfe3256e2011-11-25 12:11:43 +00002184 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00002185 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002186
Paul Bakker6c591fa2011-05-05 11:49:20 +00002187 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002188
2189 n = BITS_TO_LIMBS( nbits );
2190
Paul Bakker901c6562012-04-20 13:25:38 +00002191 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002192
2193 k = mpi_msb( X );
Pascal Junodb99183d2015-03-11 16:49:45 +01002194 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002195
Pascal Junodb99183d2015-03-11 16:49:45 +01002196 mpi_set_bit( X, nbits-1, 1 );
2197
2198 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002199
2200 if( dh_flag == 0 )
2201 {
2202 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
2203 {
Paul Bakker40e46942009-01-03 21:51:57 +00002204 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002205 goto cleanup;
2206
2207 MPI_CHK( mpi_add_int( X, X, 2 ) );
2208 }
2209 }
2210 else
2211 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002212 /*
2213 * An necessary condition for Y and X = 2Y + 1 to be prime
2214 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2215 * Make sure it is satisfied, while keeping X = 3 mod 4
2216 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002217
2218 X->p[0] |= 2;
2219
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002220 MPI_CHK( mpi_mod_int( &r, X, 3 ) );
2221 if( r == 0 )
2222 MPI_CHK( mpi_add_int( X, X, 8 ) );
2223 else if( r == 1 )
2224 MPI_CHK( mpi_add_int( X, X, 4 ) );
2225
2226 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2227 MPI_CHK( mpi_copy( &Y, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002228 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2229
2230 while( 1 )
2231 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002232 /*
2233 * First, check small factors for X and Y
2234 * before doing Miller-Rabin on any of them
2235 */
2236 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2237 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2238 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2239 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002240 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002241 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002242 }
2243
Paul Bakker40e46942009-01-03 21:51:57 +00002244 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002245 goto cleanup;
2246
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002247 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002248 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002249 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2250 * so up Y by 6 and X by 12.
2251 */
2252 MPI_CHK( mpi_add_int( X, X, 12 ) );
2253 MPI_CHK( mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002254 }
2255 }
2256
2257cleanup:
2258
Paul Bakker6c591fa2011-05-05 11:49:20 +00002259 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002260
2261 return( ret );
2262}
2263
Manuel Pégourié-Gonnarddf0142b2013-08-22 18:29:07 +02002264#endif /* POLARSSL_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002265
Paul Bakker40e46942009-01-03 21:51:57 +00002266#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002267
Paul Bakker23986e52011-04-24 08:57:21 +00002268#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002269
2270static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2271{
2272 { 693, 609, 21 },
2273 { 1764, 868, 28 },
2274 { 768454923, 542167814, 1 }
2275};
2276
Paul Bakker5121ce52009-01-03 21:22:43 +00002277/*
2278 * Checkup routine
2279 */
2280int mpi_self_test( int verbose )
2281{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002282 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002283 mpi A, E, N, X, Y, U, V;
2284
Paul Bakker6c591fa2011-05-05 11:49:20 +00002285 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2286 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002287
2288 MPI_CHK( mpi_read_string( &A, 16,
2289 "EFE021C2645FD1DC586E69184AF4A31E" \
2290 "D5F53E93B5F123FA41680867BA110131" \
2291 "944FE7952E2517337780CB0DB80E61AA" \
2292 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2293
2294 MPI_CHK( mpi_read_string( &E, 16,
2295 "B2E7EFD37075B9F03FF989C7C5051C20" \
2296 "34D2A323810251127E7BF8625A4F49A5" \
2297 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2298 "5B5C25763222FEFCCFC38B832366C29E" ) );
2299
2300 MPI_CHK( mpi_read_string( &N, 16,
2301 "0066A198186C18C10B2F5ED9B522752A" \
2302 "9830B69916E535C8F047518A889A43A5" \
2303 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2304
2305 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2306
2307 MPI_CHK( mpi_read_string( &U, 16,
2308 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2309 "9E857EA95A03512E2BAE7391688D264A" \
2310 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2311 "8001B72E848A38CAE1C65F78E56ABDEF" \
2312 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2313 "ECF677152EF804370C1A305CAF3B5BF1" \
2314 "30879B56C61DE584A0F53A2447A51E" ) );
2315
2316 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002317 polarssl_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002318
2319 if( mpi_cmp_mpi( &X, &U ) != 0 )
2320 {
2321 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002322 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002323
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002324 ret = 1;
2325 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002326 }
2327
2328 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002329 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002330
2331 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2332
2333 MPI_CHK( mpi_read_string( &U, 16,
2334 "256567336059E52CAE22925474705F39A94" ) );
2335
2336 MPI_CHK( mpi_read_string( &V, 16,
2337 "6613F26162223DF488E9CD48CC132C7A" \
2338 "0AC93C701B001B092E4E5B9F73BCD27B" \
2339 "9EE50D0657C77F374E903CDFA4C642" ) );
2340
2341 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002342 polarssl_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002343
2344 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2345 mpi_cmp_mpi( &Y, &V ) != 0 )
2346 {
2347 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002348 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002349
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002350 ret = 1;
2351 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002352 }
2353
2354 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002355 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002356
2357 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2358
2359 MPI_CHK( mpi_read_string( &U, 16,
2360 "36E139AEA55215609D2816998ED020BB" \
2361 "BD96C37890F65171D948E9BC7CBAA4D9" \
2362 "325D24D6A3C12710F10A09FA08AB87" ) );
2363
2364 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002365 polarssl_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002366
2367 if( mpi_cmp_mpi( &X, &U ) != 0 )
2368 {
2369 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002370 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002371
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002372 ret = 1;
2373 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002374 }
2375
2376 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002377 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002378
2379 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2380
2381 MPI_CHK( mpi_read_string( &U, 16,
2382 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2383 "C3DBA76456363A10869622EAC2DD84EC" \
2384 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2385
2386 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002387 polarssl_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002388
2389 if( mpi_cmp_mpi( &X, &U ) != 0 )
2390 {
2391 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002392 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002393
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002394 ret = 1;
2395 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002396 }
2397
2398 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002399 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002400
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002401 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002402 polarssl_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002403
Paul Bakker66d5d072014-06-17 16:39:18 +02002404 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002405 {
2406 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002407 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002408
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002409 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002410
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002411 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2412 {
2413 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002414 polarssl_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002415
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002416 ret = 1;
2417 goto cleanup;
2418 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002419 }
2420
2421 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002422 polarssl_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002423
Paul Bakker5121ce52009-01-03 21:22:43 +00002424cleanup:
2425
2426 if( ret != 0 && verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002427 polarssl_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002428
Paul Bakker6c591fa2011-05-05 11:49:20 +00002429 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2430 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002431
2432 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002433 polarssl_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002434
2435 return( ret );
2436}
2437
Paul Bakker9af723c2014-05-01 13:03:14 +02002438#endif /* POLARSSL_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002439
Paul Bakker9af723c2014-05-01 13:03:14 +02002440#endif /* POLARSSL_BIGNUM_C */