blob: 9d12a86cc49b464d9370d8f44bfe071687bd8759 [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;
Andres AG2b2fc112017-03-01 14:04:08 +0000541 /*
542 * Round up the buffer length to an even value to ensure that there is
543 * enough room for hexadecimal values that can be represented in an odd
544 * number of digits.
545 */
546 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000547
548 if( *slen < n )
549 {
550 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000551 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000552 }
553
554 p = s;
Paul Bakker6c591fa2011-05-05 11:49:20 +0000555 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000556
557 if( X->s == -1 )
558 *p++ = '-';
559
560 if( radix == 16 )
561 {
Paul Bakker23986e52011-04-24 08:57:21 +0000562 int c;
563 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000564
Paul Bakker23986e52011-04-24 08:57:21 +0000565 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000566 {
Paul Bakker23986e52011-04-24 08:57:21 +0000567 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000568 {
Paul Bakker23986e52011-04-24 08:57:21 +0000569 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000570
Paul Bakker6c343d72014-07-10 14:36:19 +0200571 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000572 continue;
573
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000574 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000575 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000576 k = 1;
577 }
578 }
579 }
580 else
581 {
582 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000583
584 if( T.s == -1 )
585 T.s = 1;
586
Paul Bakker5121ce52009-01-03 21:22:43 +0000587 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
588 }
589
590 *p++ = '\0';
591 *slen = p - s;
592
593cleanup:
594
Paul Bakker6c591fa2011-05-05 11:49:20 +0000595 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000596
597 return( ret );
598}
599
Paul Bakker335db3f2011-04-25 15:28:35 +0000600#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000601/*
602 * Read X from an opened file
603 */
604int mpi_read_file( mpi *X, int radix, FILE *fin )
605{
Paul Bakkera755ca12011-04-24 09:11:17 +0000606 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000607 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000608 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000609 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000610 * Buffer should have space for (short) label and decimal formatted MPI,
611 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000612 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000613 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000614
615 memset( s, 0, sizeof( s ) );
616 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000617 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000618
619 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000620 if( slen == sizeof( s ) - 2 )
621 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
622
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
624 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
625
626 p = s + slen;
627 while( --p >= s )
628 if( mpi_get_digit( &d, radix, *p ) != 0 )
629 break;
630
631 return( mpi_read_string( X, radix, p + 1 ) );
632}
633
634/*
635 * Write X into an opened file (or stdout if fout == NULL)
636 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000637int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000638{
Paul Bakker23986e52011-04-24 08:57:21 +0000639 int ret;
640 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000641 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000642 * Buffer should have space for (short) label and decimal formatted MPI,
643 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000644 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000645 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000646
647 n = sizeof( s );
648 memset( s, 0, n );
649 n -= 2;
650
Paul Bakker23986e52011-04-24 08:57:21 +0000651 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000652
653 if( p == NULL ) p = "";
654
655 plen = strlen( p );
656 slen = strlen( s );
657 s[slen++] = '\r';
658 s[slen++] = '\n';
659
660 if( fout != NULL )
661 {
662 if( fwrite( p, 1, plen, fout ) != plen ||
663 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000664 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000665 }
666 else
Paul Bakker7dc4c442014-02-01 22:50:26 +0100667 polarssl_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000668
669cleanup:
670
671 return( ret );
672}
Paul Bakker335db3f2011-04-25 15:28:35 +0000673#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000674
675/*
676 * Import X from unsigned binary data, big endian
677 */
Paul Bakker23986e52011-04-24 08:57:21 +0000678int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000679{
Paul Bakker23986e52011-04-24 08:57:21 +0000680 int ret;
681 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000682
683 for( n = 0; n < buflen; n++ )
684 if( buf[n] != 0 )
685 break;
686
687 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
688 MPI_CHK( mpi_lset( X, 0 ) );
689
Paul Bakker23986e52011-04-24 08:57:21 +0000690 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000691 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000692
693cleanup:
694
695 return( ret );
696}
697
698/*
699 * Export X into unsigned binary data, big endian
700 */
Paul Bakker23986e52011-04-24 08:57:21 +0000701int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000702{
Paul Bakker23986e52011-04-24 08:57:21 +0000703 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000704
705 n = mpi_size( X );
706
707 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000708 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000709
710 memset( buf, 0, buflen );
711
712 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
713 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
714
715 return( 0 );
716}
717
718/*
719 * Left-shift: X <<= count
720 */
Paul Bakker23986e52011-04-24 08:57:21 +0000721int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000722{
Paul Bakker23986e52011-04-24 08:57:21 +0000723 int ret;
724 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000725 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000726
727 v0 = count / (biL );
728 t1 = count & (biL - 1);
729
730 i = mpi_msb( X ) + count;
731
Paul Bakkerf9688572011-05-05 10:00:45 +0000732 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000733 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
734
735 ret = 0;
736
737 /*
738 * shift by count / limb_size
739 */
740 if( v0 > 0 )
741 {
Paul Bakker23986e52011-04-24 08:57:21 +0000742 for( i = X->n; i > v0; i-- )
743 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000744
Paul Bakker23986e52011-04-24 08:57:21 +0000745 for( ; i > 0; i-- )
746 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000747 }
748
749 /*
750 * shift by count % limb_size
751 */
752 if( t1 > 0 )
753 {
754 for( i = v0; i < X->n; i++ )
755 {
756 r1 = X->p[i] >> (biL - t1);
757 X->p[i] <<= t1;
758 X->p[i] |= r0;
759 r0 = r1;
760 }
761 }
762
763cleanup:
764
765 return( ret );
766}
767
768/*
769 * Right-shift: X >>= count
770 */
Paul Bakker23986e52011-04-24 08:57:21 +0000771int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000772{
Paul Bakker23986e52011-04-24 08:57:21 +0000773 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000774 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000775
776 v0 = count / biL;
777 v1 = count & (biL - 1);
778
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100779 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
780 return mpi_lset( X, 0 );
781
Paul Bakker5121ce52009-01-03 21:22:43 +0000782 /*
783 * shift by count / limb_size
784 */
785 if( v0 > 0 )
786 {
787 for( i = 0; i < X->n - v0; i++ )
788 X->p[i] = X->p[i + v0];
789
790 for( ; i < X->n; i++ )
791 X->p[i] = 0;
792 }
793
794 /*
795 * shift by count % limb_size
796 */
797 if( v1 > 0 )
798 {
Paul Bakker23986e52011-04-24 08:57:21 +0000799 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000800 {
Paul Bakker23986e52011-04-24 08:57:21 +0000801 r1 = X->p[i - 1] << (biL - v1);
802 X->p[i - 1] >>= v1;
803 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000804 r0 = r1;
805 }
806 }
807
808 return( 0 );
809}
810
811/*
812 * Compare unsigned values
813 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000814int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000815{
Paul Bakker23986e52011-04-24 08:57:21 +0000816 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000817
Paul Bakker23986e52011-04-24 08:57:21 +0000818 for( i = X->n; i > 0; i-- )
819 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000820 break;
821
Paul Bakker23986e52011-04-24 08:57:21 +0000822 for( j = Y->n; j > 0; j-- )
823 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000824 break;
825
Paul Bakker23986e52011-04-24 08:57:21 +0000826 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000827 return( 0 );
828
829 if( i > j ) return( 1 );
830 if( j > i ) return( -1 );
831
Paul Bakker23986e52011-04-24 08:57:21 +0000832 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000833 {
Paul Bakker23986e52011-04-24 08:57:21 +0000834 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
835 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000836 }
837
838 return( 0 );
839}
840
841/*
842 * Compare signed values
843 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000844int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000845{
Paul Bakker23986e52011-04-24 08:57:21 +0000846 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000847
Paul Bakker23986e52011-04-24 08:57:21 +0000848 for( i = X->n; i > 0; i-- )
849 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000850 break;
851
Paul Bakker23986e52011-04-24 08:57:21 +0000852 for( j = Y->n; j > 0; j-- )
853 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000854 break;
855
Paul Bakker23986e52011-04-24 08:57:21 +0000856 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000857 return( 0 );
858
859 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000860 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000861
862 if( X->s > 0 && Y->s < 0 ) return( 1 );
863 if( Y->s > 0 && X->s < 0 ) return( -1 );
864
Paul Bakker23986e52011-04-24 08:57:21 +0000865 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000866 {
Paul Bakker23986e52011-04-24 08:57:21 +0000867 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
868 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000869 }
870
871 return( 0 );
872}
873
874/*
875 * Compare signed values
876 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000877int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000878{
879 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000880 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000881
882 *p = ( z < 0 ) ? -z : z;
883 Y.s = ( z < 0 ) ? -1 : 1;
884 Y.n = 1;
885 Y.p = p;
886
887 return( mpi_cmp_mpi( X, &Y ) );
888}
889
890/*
891 * Unsigned addition: X = |A| + |B| (HAC 14.7)
892 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000893int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000894{
Paul Bakker23986e52011-04-24 08:57:21 +0000895 int ret;
896 size_t i, j;
Manuel Pégourié-Gonnardfaae6d22016-01-08 15:24:46 +0100897 t_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000898
899 if( X == B )
900 {
Janos Follath2db440d2015-10-30 17:43:11 +0100901 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000902 }
903
904 if( X != A )
905 MPI_CHK( mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200906
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000907 /*
908 * X should always be positive as a result of unsigned additions.
909 */
910 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000911
Paul Bakker23986e52011-04-24 08:57:21 +0000912 for( j = B->n; j > 0; j-- )
913 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000914 break;
915
Paul Bakker23986e52011-04-24 08:57:21 +0000916 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000917
918 o = B->p; p = X->p; c = 0;
919
Janos Follath2db440d2015-10-30 17:43:11 +0100920 /*
921 * tmp is used because it might happen that p == o
922 */
Paul Bakker23986e52011-04-24 08:57:21 +0000923 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000924 {
Janos Follath2db440d2015-10-30 17:43:11 +0100925 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000926 *p += c; c = ( *p < c );
Janos Follath2db440d2015-10-30 17:43:11 +0100927 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000928 }
929
930 while( c != 0 )
931 {
932 if( i >= X->n )
933 {
934 MPI_CHK( mpi_grow( X, i + 1 ) );
935 p = X->p + i;
936 }
937
Paul Bakker2d319fd2012-09-16 21:34:26 +0000938 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000939 }
940
941cleanup:
Paul Bakker5121ce52009-01-03 21:22:43 +0000942 return( ret );
943}
944
945/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100946 * Helper for mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000947 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000948static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000949{
Paul Bakker23986e52011-04-24 08:57:21 +0000950 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000951 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000952
953 for( i = c = 0; i < n; i++, s++, d++ )
954 {
955 z = ( *d < c ); *d -= c;
956 c = ( *d < *s ) + z; *d -= *s;
957 }
958
959 while( c != 0 )
960 {
961 z = ( *d < c ); *d -= c;
962 c = z; i++; d++;
963 }
964}
965
966/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100967 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000968 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000969int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000970{
971 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000972 int ret;
973 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000974
975 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000976 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000977
Paul Bakker6c591fa2011-05-05 11:49:20 +0000978 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000979
980 if( X == B )
981 {
982 MPI_CHK( mpi_copy( &TB, B ) );
983 B = &TB;
984 }
985
986 if( X != A )
987 MPI_CHK( mpi_copy( X, A ) );
988
Paul Bakker1ef7a532009-06-20 10:50:55 +0000989 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100990 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000991 */
992 X->s = 1;
993
Paul Bakker5121ce52009-01-03 21:22:43 +0000994 ret = 0;
995
Paul Bakker23986e52011-04-24 08:57:21 +0000996 for( n = B->n; n > 0; n-- )
997 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000998 break;
999
Paul Bakker23986e52011-04-24 08:57:21 +00001000 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001001
1002cleanup:
1003
Paul Bakker6c591fa2011-05-05 11:49:20 +00001004 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001005
1006 return( ret );
1007}
1008
1009/*
1010 * Signed addition: X = A + B
1011 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001012int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001013{
1014 int ret, s = A->s;
1015
1016 if( A->s * B->s < 0 )
1017 {
1018 if( mpi_cmp_abs( A, B ) >= 0 )
1019 {
1020 MPI_CHK( mpi_sub_abs( X, A, B ) );
1021 X->s = s;
1022 }
1023 else
1024 {
1025 MPI_CHK( mpi_sub_abs( X, B, A ) );
1026 X->s = -s;
1027 }
1028 }
1029 else
1030 {
1031 MPI_CHK( mpi_add_abs( X, A, B ) );
1032 X->s = s;
1033 }
1034
1035cleanup:
1036
1037 return( ret );
1038}
1039
1040/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001041 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001042 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001043int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001044{
1045 int ret, s = A->s;
1046
1047 if( A->s * B->s > 0 )
1048 {
1049 if( mpi_cmp_abs( A, B ) >= 0 )
1050 {
1051 MPI_CHK( mpi_sub_abs( X, A, B ) );
1052 X->s = s;
1053 }
1054 else
1055 {
1056 MPI_CHK( mpi_sub_abs( X, B, A ) );
1057 X->s = -s;
1058 }
1059 }
1060 else
1061 {
1062 MPI_CHK( mpi_add_abs( X, A, B ) );
1063 X->s = s;
1064 }
1065
1066cleanup:
1067
1068 return( ret );
1069}
1070
1071/*
1072 * Signed addition: X = A + b
1073 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001074int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001075{
1076 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001077 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001078
1079 p[0] = ( b < 0 ) ? -b : b;
1080 _B.s = ( b < 0 ) ? -1 : 1;
1081 _B.n = 1;
1082 _B.p = p;
1083
1084 return( mpi_add_mpi( X, A, &_B ) );
1085}
1086
1087/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001088 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001089 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001090int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001091{
1092 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001093 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001094
1095 p[0] = ( b < 0 ) ? -b : b;
1096 _B.s = ( b < 0 ) ? -1 : 1;
1097 _B.n = 1;
1098 _B.p = p;
1099
1100 return( mpi_sub_mpi( X, A, &_B ) );
1101}
1102
1103/*
1104 * Helper for mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001105 */
1106static
1107#if defined(__APPLE__) && defined(__arm__)
1108/*
1109 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1110 * appears to need this to prevent bad ARM code generation at -O3.
1111 */
1112__attribute__ ((noinline))
1113#endif
1114void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001115{
Paul Bakkera755ca12011-04-24 09:11:17 +00001116 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001117
1118#if defined(MULADDC_HUIT)
1119 for( ; i >= 8; i -= 8 )
1120 {
1121 MULADDC_INIT
1122 MULADDC_HUIT
1123 MULADDC_STOP
1124 }
1125
1126 for( ; i > 0; i-- )
1127 {
1128 MULADDC_INIT
1129 MULADDC_CORE
1130 MULADDC_STOP
1131 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001132#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001133 for( ; i >= 16; i -= 16 )
1134 {
1135 MULADDC_INIT
1136 MULADDC_CORE MULADDC_CORE
1137 MULADDC_CORE MULADDC_CORE
1138 MULADDC_CORE MULADDC_CORE
1139 MULADDC_CORE MULADDC_CORE
1140
1141 MULADDC_CORE MULADDC_CORE
1142 MULADDC_CORE MULADDC_CORE
1143 MULADDC_CORE MULADDC_CORE
1144 MULADDC_CORE MULADDC_CORE
1145 MULADDC_STOP
1146 }
1147
1148 for( ; i >= 8; i -= 8 )
1149 {
1150 MULADDC_INIT
1151 MULADDC_CORE MULADDC_CORE
1152 MULADDC_CORE MULADDC_CORE
1153
1154 MULADDC_CORE MULADDC_CORE
1155 MULADDC_CORE MULADDC_CORE
1156 MULADDC_STOP
1157 }
1158
1159 for( ; i > 0; i-- )
1160 {
1161 MULADDC_INIT
1162 MULADDC_CORE
1163 MULADDC_STOP
1164 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001165#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001166
1167 t++;
1168
1169 do {
1170 *d += c; c = ( *d < c ); d++;
1171 }
1172 while( c != 0 );
1173}
1174
1175/*
1176 * Baseline multiplication: X = A * B (HAC 14.12)
1177 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001178int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001179{
Paul Bakker23986e52011-04-24 08:57:21 +00001180 int ret;
1181 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001182 mpi TA, TB;
1183
Paul Bakker6c591fa2011-05-05 11:49:20 +00001184 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001185
1186 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1187 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1188
Paul Bakker23986e52011-04-24 08:57:21 +00001189 for( i = A->n; i > 0; i-- )
1190 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001191 break;
1192
Paul Bakker23986e52011-04-24 08:57:21 +00001193 for( j = B->n; j > 0; j-- )
1194 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001195 break;
1196
Paul Bakker23986e52011-04-24 08:57:21 +00001197 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001198 MPI_CHK( mpi_lset( X, 0 ) );
1199
Paul Bakker23986e52011-04-24 08:57:21 +00001200 for( i++; j > 0; j-- )
1201 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001202
1203 X->s = A->s * B->s;
1204
1205cleanup:
1206
Paul Bakker6c591fa2011-05-05 11:49:20 +00001207 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001208
1209 return( ret );
1210}
1211
1212/*
1213 * Baseline multiplication: X = A * b
1214 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001215int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001216{
1217 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001218 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001219
1220 _B.s = 1;
1221 _B.n = 1;
1222 _B.p = p;
1223 p[0] = b;
1224
1225 return( mpi_mul_mpi( X, A, &_B ) );
1226}
1227
1228/*
Simon Butcher14400c82016-01-02 00:08:13 +00001229 * Unsigned integer divide - double t_uint, dividend, u1/u0, and t_uint
1230 * divisor, d
Simon Butchere4ed3472015-12-22 15:26:57 +00001231 */
Simon Butcher14400c82016-01-02 00:08:13 +00001232static t_uint int_div_int( t_uint u1, t_uint u0, t_uint d, t_uint *r )
Simon Butchere4ed3472015-12-22 15:26:57 +00001233{
1234#if defined(POLARSSL_HAVE_UDBL)
1235 t_udbl dividend, quotient;
Simon Butcher14400c82016-01-02 00:08:13 +00001236#else
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001237 const t_uint radix = (t_uint) 1 << biH;
1238 const t_uint uint_halfword_mask = ( (t_uint) 1 << biH ) - 1;
Simon Butcher14400c82016-01-02 00:08:13 +00001239 t_uint d0, d1, q0, q1, rAX, r0, quotient;
1240 t_uint u0_msw, u0_lsw;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001241 size_t s;
Simon Butchere4ed3472015-12-22 15:26:57 +00001242#endif
1243
1244 /*
1245 * Check for overflow
1246 */
Simon Butcher14400c82016-01-02 00:08:13 +00001247 if( 0 == d || u1 >= d )
Simon Butchere4ed3472015-12-22 15:26:57 +00001248 {
Simon Butcher14400c82016-01-02 00:08:13 +00001249 if ( r != NULL ) *r = ~0;
Simon Butchere4ed3472015-12-22 15:26:57 +00001250
Simon Butcher14400c82016-01-02 00:08:13 +00001251 return ( ~0 );
Simon Butchere4ed3472015-12-22 15:26:57 +00001252 }
1253
1254#if defined(POLARSSL_HAVE_UDBL)
1255 dividend = (t_udbl) u1 << biL;
1256 dividend |= (t_udbl) u0;
1257 quotient = dividend / d;
1258 if( quotient > ( (t_udbl) 1 << biL ) - 1 )
1259 quotient = ( (t_udbl) 1 << biL ) - 1;
1260
1261 if( r != NULL )
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001262 *r = (t_uint)( dividend - (quotient * d ) );
Simon Butchere4ed3472015-12-22 15:26:57 +00001263
1264 return (t_uint) quotient;
1265#else
Simon Butchere4ed3472015-12-22 15:26:57 +00001266
1267 /*
1268 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1269 * Vol. 2 - Seminumerical Algorithms, Knuth
1270 */
1271
1272 /*
1273 * Normalize the divisor, d, and dividend, u0, u1
1274 */
1275 s = int_clz( d );
1276 d = d << s;
1277
1278 u1 = u1 << s;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001279 u1 |= ( u0 >> ( biL - s ) ) & ( -(t_sint)s >> ( biL - 1 ) );
Simon Butchere4ed3472015-12-22 15:26:57 +00001280 u0 = u0 << s;
1281
1282 d1 = d >> biH;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001283 d0 = d & uint_halfword_mask;
Simon Butchere4ed3472015-12-22 15:26:57 +00001284
1285 u0_msw = u0 >> biH;
Simon Butcherd7fe6fb2016-01-03 22:39:18 +00001286 u0_lsw = u0 & uint_halfword_mask;
Simon Butchere4ed3472015-12-22 15:26:57 +00001287
1288 /*
1289 * Find the first quotient and remainder
1290 */
1291 q1 = u1 / d1;
1292 r0 = u1 - d1 * q1;
1293
1294 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1295 {
1296 q1 -= 1;
1297 r0 += d1;
1298
1299 if ( r0 >= radix ) break;
1300 }
1301
Simon Butcher14400c82016-01-02 00:08:13 +00001302 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butchere4ed3472015-12-22 15:26:57 +00001303 q0 = rAX / d1;
1304 r0 = rAX - q0 * d1;
1305
1306 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1307 {
1308 q0 -= 1;
1309 r0 += d1;
1310
1311 if ( r0 >= radix ) break;
1312 }
1313
1314 if (r != NULL)
Simon Butcher14400c82016-01-02 00:08:13 +00001315 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butchere4ed3472015-12-22 15:26:57 +00001316
1317 quotient = q1 * radix + q0;
1318
1319 return quotient;
1320#endif
1321}
1322
1323/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001324 * Division by mpi: A = Q * B + R (HAC 14.20)
1325 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001326int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001327{
Paul Bakker23986e52011-04-24 08:57:21 +00001328 int ret;
1329 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001330 mpi X, Y, Z, T1, T2;
1331
1332 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001333 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001334
Paul Bakker6c591fa2011-05-05 11:49:20 +00001335 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1336 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001337
1338 if( mpi_cmp_abs( A, B ) < 0 )
1339 {
1340 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1341 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1342 return( 0 );
1343 }
1344
1345 MPI_CHK( mpi_copy( &X, A ) );
1346 MPI_CHK( mpi_copy( &Y, B ) );
1347 X.s = Y.s = 1;
1348
1349 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1350 MPI_CHK( mpi_lset( &Z, 0 ) );
1351 MPI_CHK( mpi_grow( &T1, 2 ) );
1352 MPI_CHK( mpi_grow( &T2, 3 ) );
1353
1354 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001355 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001356 {
1357 k = biL - 1 - k;
1358 MPI_CHK( mpi_shift_l( &X, k ) );
1359 MPI_CHK( mpi_shift_l( &Y, k ) );
1360 }
1361 else k = 0;
1362
1363 n = X.n - 1;
1364 t = Y.n - 1;
Paul Bakker66d5d072014-06-17 16:39:18 +02001365 MPI_CHK( mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001366
1367 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1368 {
1369 Z.p[n - t]++;
Paul Bakker6ea1a952013-12-31 11:16:03 +01001370 MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001371 }
Paul Bakker66d5d072014-06-17 16:39:18 +02001372 MPI_CHK( mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001373
1374 for( i = n; i > t ; i-- )
1375 {
1376 if( X.p[i] >= Y.p[t] )
1377 Z.p[i - t - 1] = ~0;
1378 else
1379 {
Simon Butchere4ed3472015-12-22 15:26:57 +00001380 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 +00001381 }
1382
1383 Z.p[i - t - 1]++;
1384 do
1385 {
1386 Z.p[i - t - 1]--;
1387
1388 MPI_CHK( mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001389 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001390 T1.p[1] = Y.p[t];
1391 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1392
1393 MPI_CHK( mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001394 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1395 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001396 T2.p[2] = X.p[i];
1397 }
1398 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1399
1400 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001401 MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001402 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1403
1404 if( mpi_cmp_int( &X, 0 ) < 0 )
1405 {
1406 MPI_CHK( mpi_copy( &T1, &Y ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001407 MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001408 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1409 Z.p[i - t - 1]--;
1410 }
1411 }
1412
1413 if( Q != NULL )
1414 {
Paul Bakker6ea1a952013-12-31 11:16:03 +01001415 MPI_CHK( mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001416 Q->s = A->s * B->s;
1417 }
1418
1419 if( R != NULL )
1420 {
Paul Bakker6ea1a952013-12-31 11:16:03 +01001421 MPI_CHK( mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001422 X.s = A->s;
Paul Bakker6ea1a952013-12-31 11:16:03 +01001423 MPI_CHK( mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001424
Paul Bakker5121ce52009-01-03 21:22:43 +00001425 if( mpi_cmp_int( R, 0 ) == 0 )
1426 R->s = 1;
1427 }
1428
1429cleanup:
1430
Paul Bakker6c591fa2011-05-05 11:49:20 +00001431 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1432 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001433
1434 return( ret );
1435}
1436
1437/*
1438 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001439 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001440int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001441{
1442 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001443 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001444
1445 p[0] = ( b < 0 ) ? -b : b;
1446 _B.s = ( b < 0 ) ? -1 : 1;
1447 _B.n = 1;
1448 _B.p = p;
1449
1450 return( mpi_div_mpi( Q, R, A, &_B ) );
1451}
1452
1453/*
1454 * Modulo: R = A mod B
1455 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001456int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001457{
1458 int ret;
1459
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001460 if( mpi_cmp_int( B, 0 ) < 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001461 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001462
Paul Bakker5121ce52009-01-03 21:22:43 +00001463 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1464
1465 while( mpi_cmp_int( R, 0 ) < 0 )
1466 MPI_CHK( mpi_add_mpi( R, R, B ) );
1467
1468 while( mpi_cmp_mpi( R, B ) >= 0 )
1469 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1470
1471cleanup:
1472
1473 return( ret );
1474}
1475
1476/*
1477 * Modulo: r = A mod b
1478 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001479int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001480{
Paul Bakker23986e52011-04-24 08:57:21 +00001481 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001482 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001483
1484 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001485 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001486
1487 if( b < 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001488 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001489
1490 /*
1491 * handle trivial cases
1492 */
1493 if( b == 1 )
1494 {
1495 *r = 0;
1496 return( 0 );
1497 }
1498
1499 if( b == 2 )
1500 {
1501 *r = A->p[0] & 1;
1502 return( 0 );
1503 }
1504
1505 /*
1506 * general case
1507 */
Paul Bakker23986e52011-04-24 08:57:21 +00001508 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001509 {
Paul Bakker23986e52011-04-24 08:57:21 +00001510 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001511 y = ( y << biH ) | ( x >> biH );
1512 z = y / b;
1513 y -= z * b;
1514
1515 x <<= biH;
1516 y = ( y << biH ) | ( x >> biH );
1517 z = y / b;
1518 y -= z * b;
1519 }
1520
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001521 /*
1522 * If A is negative, then the current y represents a negative value.
1523 * Flipping it to the positive side.
1524 */
1525 if( A->s < 0 && y != 0 )
1526 y = b - y;
1527
Paul Bakker5121ce52009-01-03 21:22:43 +00001528 *r = y;
1529
1530 return( 0 );
1531}
1532
1533/*
1534 * Fast Montgomery initialization (thanks to Tom St Denis)
1535 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001536static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001537{
Paul Bakkera755ca12011-04-24 09:11:17 +00001538 t_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001539 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001540
1541 x = m0;
1542 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001543
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001544 for( i = biL; i >= 8; i /= 2 )
1545 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001546
1547 *mm = ~x + 1;
1548}
1549
1550/*
1551 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1552 */
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02001553static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm,
1554 const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001555{
Paul Bakker23986e52011-04-24 08:57:21 +00001556 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001557 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001558
1559 memset( T->p, 0, T->n * ciL );
1560
1561 d = T->p;
1562 n = N->n;
1563 m = ( B->n < n ) ? B->n : n;
1564
1565 for( i = 0; i < n; i++ )
1566 {
1567 /*
1568 * T = (T + u0*B + u1*N) / 2^biL
1569 */
1570 u0 = A->p[i];
1571 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1572
1573 mpi_mul_hlp( m, B->p, d, u0 );
1574 mpi_mul_hlp( n, N->p, d, u1 );
1575
1576 *d++ = u0; d[n + 1] = 0;
1577 }
1578
Paul Bakker66d5d072014-06-17 16:39:18 +02001579 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001580
1581 if( mpi_cmp_abs( A, N ) >= 0 )
1582 mpi_sub_hlp( n, N->p, A->p );
1583 else
1584 /* prevent timing attacks */
1585 mpi_sub_hlp( n, A->p, T->p );
1586}
1587
1588/*
1589 * Montgomery reduction: A = A * R^-1 mod N
1590 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001591static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001592{
Paul Bakkera755ca12011-04-24 09:11:17 +00001593 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001594 mpi U;
1595
Paul Bakker8ddb6452013-02-27 14:56:33 +01001596 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001597 U.p = &z;
1598
1599 mpi_montmul( A, &U, N, mm, T );
1600}
1601
1602/*
1603 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1604 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001605int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001606{
Paul Bakker23986e52011-04-24 08:57:21 +00001607 int ret;
1608 size_t wbits, wsize, one = 1;
1609 size_t i, j, nblimbs;
1610 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001611 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001612 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1613 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001614
1615 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001616 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001617
Paul Bakkerf6198c12012-05-16 08:02:29 +00001618 if( mpi_cmp_int( E, 0 ) < 0 )
1619 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1620
1621 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001622 * Init temps and window size
1623 */
1624 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001625 mpi_init( &RR ); mpi_init( &T );
Manuel Pégourié-Gonnardfd6a1912014-01-18 19:05:23 +01001626 mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001627 memset( W, 0, sizeof( W ) );
1628
1629 i = mpi_msb( E );
1630
1631 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1632 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1633
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001634 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1635 wsize = POLARSSL_MPI_WINDOW_SIZE;
1636
Paul Bakker5121ce52009-01-03 21:22:43 +00001637 j = N->n + 1;
1638 MPI_CHK( mpi_grow( X, j ) );
1639 MPI_CHK( mpi_grow( &W[1], j ) );
1640 MPI_CHK( mpi_grow( &T, j * 2 ) );
1641
1642 /*
Paul Bakker50546922012-05-19 08:40:49 +00001643 * Compensate for negative A (and correct at the end)
1644 */
1645 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001646 if( neg )
1647 {
1648 MPI_CHK( mpi_copy( &Apos, A ) );
1649 Apos.s = 1;
1650 A = &Apos;
1651 }
1652
1653 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001654 * If 1st call, pre-compute R^2 mod N
1655 */
1656 if( _RR == NULL || _RR->p == NULL )
1657 {
1658 MPI_CHK( mpi_lset( &RR, 1 ) );
1659 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1660 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1661
1662 if( _RR != NULL )
1663 memcpy( _RR, &RR, sizeof( mpi ) );
1664 }
1665 else
1666 memcpy( &RR, _RR, sizeof( mpi ) );
1667
1668 /*
1669 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1670 */
1671 if( mpi_cmp_mpi( A, N ) >= 0 )
Paul Bakkerc2024f42014-01-23 20:38:35 +01001672 MPI_CHK( mpi_mod_mpi( &W[1], A, N ) );
1673 else
1674 MPI_CHK( mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001675
1676 mpi_montmul( &W[1], &RR, N, mm, &T );
1677
1678 /*
1679 * X = R^2 * R^-1 mod N = R mod N
1680 */
1681 MPI_CHK( mpi_copy( X, &RR ) );
1682 mpi_montred( X, N, mm, &T );
1683
1684 if( wsize > 1 )
1685 {
1686 /*
1687 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1688 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001689 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001690
1691 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1692 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1693
1694 for( i = 0; i < wsize - 1; i++ )
1695 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001696
Paul Bakker5121ce52009-01-03 21:22:43 +00001697 /*
1698 * W[i] = W[i - 1] * W[1]
1699 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001700 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001701 {
1702 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1703 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1704
1705 mpi_montmul( &W[i], &W[1], N, mm, &T );
1706 }
1707 }
1708
1709 nblimbs = E->n;
1710 bufsize = 0;
1711 nbits = 0;
1712 wbits = 0;
1713 state = 0;
1714
1715 while( 1 )
1716 {
1717 if( bufsize == 0 )
1718 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001719 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001720 break;
1721
Paul Bakker0d7702c2013-10-29 16:18:35 +01001722 nblimbs--;
1723
Paul Bakkera755ca12011-04-24 09:11:17 +00001724 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001725 }
1726
1727 bufsize--;
1728
1729 ei = (E->p[nblimbs] >> bufsize) & 1;
1730
1731 /*
1732 * skip leading 0s
1733 */
1734 if( ei == 0 && state == 0 )
1735 continue;
1736
1737 if( ei == 0 && state == 1 )
1738 {
1739 /*
1740 * out of window, square X
1741 */
1742 mpi_montmul( X, X, N, mm, &T );
1743 continue;
1744 }
1745
1746 /*
1747 * add ei to current window
1748 */
1749 state = 2;
1750
1751 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001752 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001753
1754 if( nbits == wsize )
1755 {
1756 /*
1757 * X = X^wsize R^-1 mod N
1758 */
1759 for( i = 0; i < wsize; i++ )
1760 mpi_montmul( X, X, N, mm, &T );
1761
1762 /*
1763 * X = X * W[wbits] R^-1 mod N
1764 */
1765 mpi_montmul( X, &W[wbits], N, mm, &T );
1766
1767 state--;
1768 nbits = 0;
1769 wbits = 0;
1770 }
1771 }
1772
1773 /*
1774 * process the remaining bits
1775 */
1776 for( i = 0; i < nbits; i++ )
1777 {
1778 mpi_montmul( X, X, N, mm, &T );
1779
1780 wbits <<= 1;
1781
Paul Bakker66d5d072014-06-17 16:39:18 +02001782 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001783 mpi_montmul( X, &W[1], N, mm, &T );
1784 }
1785
1786 /*
1787 * X = A^E * R * R^-1 mod N = A^E mod N
1788 */
1789 mpi_montred( X, N, mm, &T );
1790
Hanno Becker88bbab22017-05-11 15:57:15 +01001791 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001792 {
1793 X->s = -1;
Paul Bakkerc2024f42014-01-23 20:38:35 +01001794 MPI_CHK( mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001795 }
1796
Paul Bakker5121ce52009-01-03 21:22:43 +00001797cleanup:
1798
Paul Bakker66d5d072014-06-17 16:39:18 +02001799 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001800 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001801
Paul Bakkerf6198c12012-05-16 08:02:29 +00001802 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001803
Paul Bakker75a28602014-03-31 12:08:17 +02001804 if( _RR == NULL || _RR->p == NULL )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001805 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001806
1807 return( ret );
1808}
1809
Paul Bakker5121ce52009-01-03 21:22:43 +00001810/*
1811 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1812 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001813int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001814{
Paul Bakker23986e52011-04-24 08:57:21 +00001815 int ret;
1816 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001817 mpi TG, TA, TB;
1818
Paul Bakker6c591fa2011-05-05 11:49:20 +00001819 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001820
Paul Bakker5121ce52009-01-03 21:22:43 +00001821 MPI_CHK( mpi_copy( &TA, A ) );
1822 MPI_CHK( mpi_copy( &TB, B ) );
1823
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001824 lz = mpi_lsb( &TA );
1825 lzt = mpi_lsb( &TB );
1826
Paul Bakker66d5d072014-06-17 16:39:18 +02001827 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001828 lz = lzt;
1829
1830 MPI_CHK( mpi_shift_r( &TA, lz ) );
1831 MPI_CHK( mpi_shift_r( &TB, lz ) );
1832
Paul Bakker5121ce52009-01-03 21:22:43 +00001833 TA.s = TB.s = 1;
1834
1835 while( mpi_cmp_int( &TA, 0 ) != 0 )
1836 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001837 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1838 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001839
1840 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1841 {
1842 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1843 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1844 }
1845 else
1846 {
1847 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1848 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1849 }
1850 }
1851
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001852 MPI_CHK( mpi_shift_l( &TB, lz ) );
1853 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001854
1855cleanup:
1856
Paul Bakker6c591fa2011-05-05 11:49:20 +00001857 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001858
1859 return( ret );
1860}
1861
Paul Bakker33dc46b2014-04-30 16:11:39 +02001862/*
1863 * Fill X with size bytes of random.
1864 *
1865 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001866 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001867 * deterministic, eg for tests).
1868 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001869int mpi_fill_random( mpi *X, size_t size,
1870 int (*f_rng)(void *, unsigned char *, size_t),
1871 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001872{
Paul Bakker23986e52011-04-24 08:57:21 +00001873 int ret;
Paul Bakker33dc46b2014-04-30 16:11:39 +02001874 unsigned char buf[POLARSSL_MPI_MAX_SIZE];
1875
1876 if( size > POLARSSL_MPI_MAX_SIZE )
1877 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001878
Paul Bakker33dc46b2014-04-30 16:11:39 +02001879 MPI_CHK( f_rng( p_rng, buf, size ) );
1880 MPI_CHK( mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001881
1882cleanup:
1883 return( ret );
1884}
1885
Paul Bakker5121ce52009-01-03 21:22:43 +00001886/*
1887 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1888 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001889int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001890{
1891 int ret;
1892 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1893
Hanno Becker1c6339f2017-05-11 15:59:11 +01001894 if( mpi_cmp_int( N, 1 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001895 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001896
Paul Bakker6c591fa2011-05-05 11:49:20 +00001897 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1898 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1899 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001900
1901 MPI_CHK( mpi_gcd( &G, A, N ) );
1902
1903 if( mpi_cmp_int( &G, 1 ) != 0 )
1904 {
Paul Bakker40e46942009-01-03 21:51:57 +00001905 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001906 goto cleanup;
1907 }
1908
1909 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1910 MPI_CHK( mpi_copy( &TU, &TA ) );
1911 MPI_CHK( mpi_copy( &TB, N ) );
1912 MPI_CHK( mpi_copy( &TV, N ) );
1913
1914 MPI_CHK( mpi_lset( &U1, 1 ) );
1915 MPI_CHK( mpi_lset( &U2, 0 ) );
1916 MPI_CHK( mpi_lset( &V1, 0 ) );
1917 MPI_CHK( mpi_lset( &V2, 1 ) );
1918
1919 do
1920 {
1921 while( ( TU.p[0] & 1 ) == 0 )
1922 {
1923 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1924
1925 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1926 {
1927 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1928 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1929 }
1930
1931 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1932 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1933 }
1934
1935 while( ( TV.p[0] & 1 ) == 0 )
1936 {
1937 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1938
1939 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1940 {
1941 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1942 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1943 }
1944
1945 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1946 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1947 }
1948
1949 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1950 {
1951 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1952 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1953 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1954 }
1955 else
1956 {
1957 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1958 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1959 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1960 }
1961 }
1962 while( mpi_cmp_int( &TU, 0 ) != 0 );
1963
1964 while( mpi_cmp_int( &V1, 0 ) < 0 )
1965 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1966
1967 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1968 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1969
1970 MPI_CHK( mpi_copy( X, &V1 ) );
1971
1972cleanup:
1973
Paul Bakker6c591fa2011-05-05 11:49:20 +00001974 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1975 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1976 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001977
1978 return( ret );
1979}
1980
Paul Bakkerd9374b02012-11-02 11:02:58 +00001981#if defined(POLARSSL_GENPRIME)
1982
Paul Bakker5121ce52009-01-03 21:22:43 +00001983static const int small_prime[] =
1984{
1985 3, 5, 7, 11, 13, 17, 19, 23,
1986 29, 31, 37, 41, 43, 47, 53, 59,
1987 61, 67, 71, 73, 79, 83, 89, 97,
1988 101, 103, 107, 109, 113, 127, 131, 137,
1989 139, 149, 151, 157, 163, 167, 173, 179,
1990 181, 191, 193, 197, 199, 211, 223, 227,
1991 229, 233, 239, 241, 251, 257, 263, 269,
1992 271, 277, 281, 283, 293, 307, 311, 313,
1993 317, 331, 337, 347, 349, 353, 359, 367,
1994 373, 379, 383, 389, 397, 401, 409, 419,
1995 421, 431, 433, 439, 443, 449, 457, 461,
1996 463, 467, 479, 487, 491, 499, 503, 509,
1997 521, 523, 541, 547, 557, 563, 569, 571,
1998 577, 587, 593, 599, 601, 607, 613, 617,
1999 619, 631, 641, 643, 647, 653, 659, 661,
2000 673, 677, 683, 691, 701, 709, 719, 727,
2001 733, 739, 743, 751, 757, 761, 769, 773,
2002 787, 797, 809, 811, 821, 823, 827, 829,
2003 839, 853, 857, 859, 863, 877, 881, 883,
2004 887, 907, 911, 919, 929, 937, 941, 947,
2005 953, 967, 971, 977, 983, 991, 997, -103
2006};
2007
2008/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002009 * Small divisors test (X must be positive)
2010 *
2011 * Return values:
2012 * 0: no small factor (possible prime, more tests needed)
2013 * 1: certain prime
2014 * POLARSSL_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2015 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002016 */
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002017static int mpi_check_small_factors( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002018{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002019 int ret = 0;
2020 size_t i;
2021 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
Paul Bakker5121ce52009-01-03 21:22:43 +00002023 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002024 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002025
2026 for( i = 0; small_prime[i] > 0; i++ )
2027 {
Paul Bakker5121ce52009-01-03 21:22:43 +00002028 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002029 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002030
2031 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
2032
2033 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00002034 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002035 }
2036
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002037cleanup:
2038 return( ret );
2039}
2040
2041/*
2042 * Miller-Rabin pseudo-primality test (HAC 4.24)
2043 */
2044static int mpi_miller_rabin( const mpi *X,
2045 int (*f_rng)(void *, unsigned char *, size_t),
2046 void *p_rng )
2047{
Pascal Junodb99183d2015-03-11 16:49:45 +01002048 int ret, count;
2049 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002050 mpi W, R, T, A, RR;
2051
2052 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
2053 mpi_init( &RR );
2054
Paul Bakker5121ce52009-01-03 21:22:43 +00002055 /*
2056 * W = |X| - 1
2057 * R = W >> lsb( W )
2058 */
Paul Bakker5121ce52009-01-03 21:22:43 +00002059 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00002060 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00002061 MPI_CHK( mpi_copy( &R, &W ) );
2062 MPI_CHK( mpi_shift_r( &R, s ) );
2063
2064 i = mpi_msb( X );
2065 /*
2066 * HAC, table 4.4
2067 */
2068 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2069 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2070 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2071
2072 for( i = 0; i < n; i++ )
2073 {
2074 /*
2075 * pick a random A, 1 < A < |X| - 1
2076 */
Paul Bakker5121ce52009-01-03 21:22:43 +00002077
Pascal Junodb99183d2015-03-11 16:49:45 +01002078 count = 0;
2079 do {
2080 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
2081
2082 j = mpi_msb( &A );
2083 k = mpi_msb( &W );
2084 if (j > k) {
2085 MPI_CHK( mpi_shift_r( &A, j - k ) );
2086 }
2087
2088 if (count++ > 30) {
2089 return POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
2090 }
2091
2092 } while ( (mpi_cmp_mpi( &A, &W ) >= 0) ||
2093 (mpi_cmp_int( &A, 1 ) <= 0) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002094
2095 /*
2096 * A = A^R mod |X|
2097 */
2098 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
2099
2100 if( mpi_cmp_mpi( &A, &W ) == 0 ||
2101 mpi_cmp_int( &A, 1 ) == 0 )
2102 continue;
2103
2104 j = 1;
2105 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
2106 {
2107 /*
2108 * A = A * A mod |X|
2109 */
2110 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
2111 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
2112
2113 if( mpi_cmp_int( &A, 1 ) == 0 )
2114 break;
2115
2116 j++;
2117 }
2118
2119 /*
2120 * not prime if A != |X| - 1 or A == 1
2121 */
2122 if( mpi_cmp_mpi( &A, &W ) != 0 ||
2123 mpi_cmp_int( &A, 1 ) == 0 )
2124 {
Paul Bakker40e46942009-01-03 21:51:57 +00002125 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002126 break;
2127 }
2128 }
2129
2130cleanup:
Paul Bakker6c591fa2011-05-05 11:49:20 +00002131 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
2132 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002133
2134 return( ret );
2135}
2136
2137/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002138 * Pseudo-primality test: small factors, then Miller-Rabin
2139 */
Paul Bakker45f457d2013-11-25 14:26:52 +01002140int mpi_is_prime( mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002141 int (*f_rng)(void *, unsigned char *, size_t),
2142 void *p_rng )
2143{
2144 int ret;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002145 mpi XX;
2146
2147 XX.s = 1;
2148 XX.n = X->n;
2149 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002150
2151 if( mpi_cmp_int( &XX, 0 ) == 0 ||
2152 mpi_cmp_int( &XX, 1 ) == 0 )
2153 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
2154
2155 if( mpi_cmp_int( &XX, 2 ) == 0 )
2156 return( 0 );
2157
2158 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2159 {
2160 if( ret == 1 )
2161 return( 0 );
2162
2163 return( ret );
2164 }
2165
2166 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2167}
2168
2169/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002170 * Prime number generation
2171 */
Paul Bakker23986e52011-04-24 08:57:21 +00002172int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002173 int (*f_rng)(void *, unsigned char *, size_t),
2174 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002175{
Paul Bakker23986e52011-04-24 08:57:21 +00002176 int ret;
2177 size_t k, n;
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002178 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002179 mpi Y;
2180
Paul Bakkerfe3256e2011-11-25 12:11:43 +00002181 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00002182 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002183
Paul Bakker6c591fa2011-05-05 11:49:20 +00002184 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002185
2186 n = BITS_TO_LIMBS( nbits );
2187
Paul Bakker901c6562012-04-20 13:25:38 +00002188 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002189
2190 k = mpi_msb( X );
Pascal Junodb99183d2015-03-11 16:49:45 +01002191 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002192
Pascal Junodb99183d2015-03-11 16:49:45 +01002193 mpi_set_bit( X, nbits-1, 1 );
2194
2195 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002196
2197 if( dh_flag == 0 )
2198 {
2199 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
2200 {
Paul Bakker40e46942009-01-03 21:51:57 +00002201 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002202 goto cleanup;
2203
2204 MPI_CHK( mpi_add_int( X, X, 2 ) );
2205 }
2206 }
2207 else
2208 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002209 /*
2210 * An necessary condition for Y and X = 2Y + 1 to be prime
2211 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2212 * Make sure it is satisfied, while keeping X = 3 mod 4
2213 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002214
2215 X->p[0] |= 2;
2216
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002217 MPI_CHK( mpi_mod_int( &r, X, 3 ) );
2218 if( r == 0 )
2219 MPI_CHK( mpi_add_int( X, X, 8 ) );
2220 else if( r == 1 )
2221 MPI_CHK( mpi_add_int( X, X, 4 ) );
2222
2223 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2224 MPI_CHK( mpi_copy( &Y, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002225 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2226
2227 while( 1 )
2228 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002229 /*
2230 * First, check small factors for X and Y
2231 * before doing Miller-Rabin on any of them
2232 */
2233 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2234 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2235 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2236 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002237 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002238 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002239 }
2240
Paul Bakker40e46942009-01-03 21:51:57 +00002241 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002242 goto cleanup;
2243
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002244 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002245 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002246 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2247 * so up Y by 6 and X by 12.
2248 */
2249 MPI_CHK( mpi_add_int( X, X, 12 ) );
2250 MPI_CHK( mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002251 }
2252 }
2253
2254cleanup:
2255
Paul Bakker6c591fa2011-05-05 11:49:20 +00002256 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002257
2258 return( ret );
2259}
2260
Manuel Pégourié-Gonnarddf0142b2013-08-22 18:29:07 +02002261#endif /* POLARSSL_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002262
Paul Bakker40e46942009-01-03 21:51:57 +00002263#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002264
Paul Bakker23986e52011-04-24 08:57:21 +00002265#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002266
2267static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2268{
2269 { 693, 609, 21 },
2270 { 1764, 868, 28 },
2271 { 768454923, 542167814, 1 }
2272};
2273
Paul Bakker5121ce52009-01-03 21:22:43 +00002274/*
2275 * Checkup routine
2276 */
2277int mpi_self_test( int verbose )
2278{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002279 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002280 mpi A, E, N, X, Y, U, V;
2281
Paul Bakker6c591fa2011-05-05 11:49:20 +00002282 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2283 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002284
2285 MPI_CHK( mpi_read_string( &A, 16,
2286 "EFE021C2645FD1DC586E69184AF4A31E" \
2287 "D5F53E93B5F123FA41680867BA110131" \
2288 "944FE7952E2517337780CB0DB80E61AA" \
2289 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2290
2291 MPI_CHK( mpi_read_string( &E, 16,
2292 "B2E7EFD37075B9F03FF989C7C5051C20" \
2293 "34D2A323810251127E7BF8625A4F49A5" \
2294 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2295 "5B5C25763222FEFCCFC38B832366C29E" ) );
2296
2297 MPI_CHK( mpi_read_string( &N, 16,
2298 "0066A198186C18C10B2F5ED9B522752A" \
2299 "9830B69916E535C8F047518A889A43A5" \
2300 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2301
2302 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2303
2304 MPI_CHK( mpi_read_string( &U, 16,
2305 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2306 "9E857EA95A03512E2BAE7391688D264A" \
2307 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2308 "8001B72E848A38CAE1C65F78E56ABDEF" \
2309 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2310 "ECF677152EF804370C1A305CAF3B5BF1" \
2311 "30879B56C61DE584A0F53A2447A51E" ) );
2312
2313 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002314 polarssl_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002315
2316 if( mpi_cmp_mpi( &X, &U ) != 0 )
2317 {
2318 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002319 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002320
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002321 ret = 1;
2322 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002323 }
2324
2325 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002326 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002327
2328 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2329
2330 MPI_CHK( mpi_read_string( &U, 16,
2331 "256567336059E52CAE22925474705F39A94" ) );
2332
2333 MPI_CHK( mpi_read_string( &V, 16,
2334 "6613F26162223DF488E9CD48CC132C7A" \
2335 "0AC93C701B001B092E4E5B9F73BCD27B" \
2336 "9EE50D0657C77F374E903CDFA4C642" ) );
2337
2338 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002339 polarssl_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002340
2341 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2342 mpi_cmp_mpi( &Y, &V ) != 0 )
2343 {
2344 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002345 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002347 ret = 1;
2348 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002349 }
2350
2351 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002352 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002353
2354 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2355
2356 MPI_CHK( mpi_read_string( &U, 16,
2357 "36E139AEA55215609D2816998ED020BB" \
2358 "BD96C37890F65171D948E9BC7CBAA4D9" \
2359 "325D24D6A3C12710F10A09FA08AB87" ) );
2360
2361 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002362 polarssl_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002363
2364 if( mpi_cmp_mpi( &X, &U ) != 0 )
2365 {
2366 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002367 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002368
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002369 ret = 1;
2370 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002371 }
2372
2373 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002374 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002375
2376 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2377
2378 MPI_CHK( mpi_read_string( &U, 16,
2379 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2380 "C3DBA76456363A10869622EAC2DD84EC" \
2381 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2382
2383 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002384 polarssl_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002385
2386 if( mpi_cmp_mpi( &X, &U ) != 0 )
2387 {
2388 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002389 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002390
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002391 ret = 1;
2392 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002393 }
2394
2395 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002396 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002397
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002398 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002399 polarssl_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002400
Paul Bakker66d5d072014-06-17 16:39:18 +02002401 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002402 {
2403 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002404 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002405
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002406 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002407
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002408 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2409 {
2410 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002411 polarssl_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002412
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002413 ret = 1;
2414 goto cleanup;
2415 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002416 }
2417
2418 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002419 polarssl_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002420
Paul Bakker5121ce52009-01-03 21:22:43 +00002421cleanup:
2422
2423 if( ret != 0 && verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002424 polarssl_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002425
Paul Bakker6c591fa2011-05-05 11:49:20 +00002426 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2427 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002428
2429 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002430 polarssl_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002431
2432 return( ret );
2433}
2434
Paul Bakker9af723c2014-05-01 13:03:14 +02002435#endif /* POLARSSL_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002436
Paul Bakker9af723c2014-05-01 13:03:14 +02002437#endif /* POLARSSL_BIGNUM_C */