blob: 91cbf2987a2bed38b4b5a0af3e5115bbc0fc138c [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é-Gonnard860b5162015-01-28 17:12:07 +00006 * This file is part of mbed TLS (https://polarssl.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 */
22/*
23 * This MPI implementation is based on:
24 *
25 * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
26 * http://www.stillhq.com/extracted/gnupg-api/mpi/
27 * http://math.libtomcrypt.com/files/tommath.pdf
28 */
29
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020030#if !defined(POLARSSL_CONFIG_FILE)
Paul Bakker40e46942009-01-03 21:51:57 +000031#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020032#else
33#include POLARSSL_CONFIG_FILE
34#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Paul Bakker40e46942009-01-03 21:51:57 +000036#if defined(POLARSSL_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Paul Bakker40e46942009-01-03 21:51:57 +000038#include "polarssl/bignum.h"
39#include "polarssl/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000040
Rich Evans00ab4702015-02-06 13:43:58 +000041#include <string.h>
42
Paul Bakker7dc4c442014-02-01 22:50:26 +010043#if defined(POLARSSL_PLATFORM_C)
44#include "polarssl/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020045#else
Rich Evans00ab4702015-02-06 13:43:58 +000046#include <stdio.h>
47#include <stdlib.h>
Paul Bakker7dc4c442014-02-01 22:50:26 +010048#define polarssl_printf printf
Paul Bakker6e339b52013-07-03 13:37:05 +020049#define polarssl_malloc malloc
50#define polarssl_free free
51#endif
52
Paul Bakker34617722014-06-13 17:20:13 +020053/* Implementation that should never be optimized out by the compiler */
54static void polarssl_zeroize( void *v, size_t n ) {
55 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
56}
57
Paul Bakkerf9688572011-05-05 10:00:45 +000058#define ciL (sizeof(t_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000059#define biL (ciL << 3) /* bits in limb */
60#define biH (ciL << 2) /* half limb size */
61
62/*
63 * Convert between bits/chars and number of limbs
64 */
65#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL)
66#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
67
68/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000069 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000070 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000071void mpi_init( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000072{
Paul Bakker6c591fa2011-05-05 11:49:20 +000073 if( X == NULL )
74 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000075
Paul Bakker6c591fa2011-05-05 11:49:20 +000076 X->s = 1;
77 X->n = 0;
78 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000079}
80
81/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000082 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000083 */
Paul Bakker6c591fa2011-05-05 11:49:20 +000084void mpi_free( mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000085{
Paul Bakker6c591fa2011-05-05 11:49:20 +000086 if( X == NULL )
87 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000088
Paul Bakker6c591fa2011-05-05 11:49:20 +000089 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +000090 {
Paul Bakker34617722014-06-13 17:20:13 +020091 polarssl_zeroize( X->p, X->n * ciL );
Paul Bakker6e339b52013-07-03 13:37:05 +020092 polarssl_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +000093 }
94
Paul Bakker6c591fa2011-05-05 11:49:20 +000095 X->s = 1;
96 X->n = 0;
97 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000098}
99
100/*
101 * Enlarge to the specified number of limbs
102 */
Paul Bakker23986e52011-04-24 08:57:21 +0000103int mpi_grow( mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000104{
Paul Bakkera755ca12011-04-24 09:11:17 +0000105 t_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000106
Paul Bakkerf9688572011-05-05 10:00:45 +0000107 if( nblimbs > POLARSSL_MPI_MAX_LIMBS )
Paul Bakker69e095c2011-12-10 21:55:01 +0000108 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000109
Paul Bakker5121ce52009-01-03 21:22:43 +0000110 if( X->n < nblimbs )
111 {
Paul Bakker6e339b52013-07-03 13:37:05 +0200112 if( ( p = (t_uint *) polarssl_malloc( nblimbs * ciL ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000113 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000114
115 memset( p, 0, nblimbs * ciL );
116
117 if( X->p != NULL )
118 {
119 memcpy( p, X->p, X->n * ciL );
Paul Bakker34617722014-06-13 17:20:13 +0200120 polarssl_zeroize( X->p, X->n * ciL );
Paul Bakker6e339b52013-07-03 13:37:05 +0200121 polarssl_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000122 }
123
124 X->n = nblimbs;
125 X->p = p;
126 }
127
128 return( 0 );
129}
130
131/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100132 * Resize down as much as possible,
133 * while keeping at least the specified number of limbs
134 */
135int mpi_shrink( mpi *X, size_t nblimbs )
136{
137 t_uint *p;
138 size_t i;
139
140 /* Actually resize up in this case */
141 if( X->n <= nblimbs )
142 return( mpi_grow( X, nblimbs ) );
143
144 for( i = X->n - 1; i > 0; i-- )
145 if( X->p[i] != 0 )
146 break;
147 i++;
148
149 if( i < nblimbs )
150 i = nblimbs;
151
152 if( ( p = (t_uint *) polarssl_malloc( i * ciL ) ) == NULL )
153 return( POLARSSL_ERR_MPI_MALLOC_FAILED );
154
155 memset( p, 0, i * ciL );
156
157 if( X->p != NULL )
158 {
159 memcpy( p, X->p, i * ciL );
Paul Bakker34617722014-06-13 17:20:13 +0200160 polarssl_zeroize( X->p, X->n * ciL );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100161 polarssl_free( X->p );
162 }
163
164 X->n = i;
165 X->p = p;
166
167 return( 0 );
168}
169
170/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000171 * Copy the contents of Y into X
172 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000173int mpi_copy( mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000174{
Paul Bakker23986e52011-04-24 08:57:21 +0000175 int ret;
176 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000177
178 if( X == Y )
179 return( 0 );
180
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200181 if( Y->p == NULL )
182 {
183 mpi_free( X );
184 return( 0 );
185 }
186
Paul Bakker5121ce52009-01-03 21:22:43 +0000187 for( i = Y->n - 1; i > 0; i-- )
188 if( Y->p[i] != 0 )
189 break;
190 i++;
191
192 X->s = Y->s;
193
194 MPI_CHK( mpi_grow( X, i ) );
195
196 memset( X->p, 0, X->n * ciL );
197 memcpy( X->p, Y->p, i * ciL );
198
199cleanup:
200
201 return( ret );
202}
203
204/*
205 * Swap the contents of X and Y
206 */
207void mpi_swap( mpi *X, mpi *Y )
208{
209 mpi T;
210
211 memcpy( &T, X, sizeof( mpi ) );
212 memcpy( X, Y, sizeof( mpi ) );
213 memcpy( Y, &T, sizeof( mpi ) );
214}
215
216/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100217 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100218 * about whether the assignment was made or not.
219 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100220 */
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100221int mpi_safe_cond_assign( mpi *X, const mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100222{
223 int ret = 0;
224 size_t i;
225
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100226 /* make sure assign is 0 or 1 */
227 assign = ( assign != 0 );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100228
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100229 MPI_CHK( mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100230
Paul Bakker66d5d072014-06-17 16:39:18 +0200231 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100232
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100233 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200234 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100235
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100236 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200237 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100238
239cleanup:
240 return( ret );
241}
242
243/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100244 * Conditionally swap X and Y, without leaking information
245 * about whether the swap was made or not.
246 * Here it is not ok to simply swap the pointers, which whould lead to
247 * different memory access patterns when X and Y are used afterwards.
248 */
249int mpi_safe_cond_swap( mpi *X, mpi *Y, unsigned char swap )
250{
251 int ret, s;
252 size_t i;
253 t_uint tmp;
254
255 if( X == Y )
256 return( 0 );
257
258 /* make sure swap is 0 or 1 */
259 swap = ( swap != 0 );
260
261 MPI_CHK( mpi_grow( X, Y->n ) );
262 MPI_CHK( mpi_grow( Y, X->n ) );
263
264 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200265 X->s = X->s * ( 1 - swap ) + Y->s * swap;
266 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100267
268
269 for( i = 0; i < X->n; i++ )
270 {
271 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200272 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
273 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274 }
275
276cleanup:
277 return( ret );
278}
279
280/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000281 * Set value from integer
282 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000283int mpi_lset( mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000284{
285 int ret;
286
287 MPI_CHK( mpi_grow( X, 1 ) );
288 memset( X->p, 0, X->n * ciL );
289
290 X->p[0] = ( z < 0 ) ? -z : z;
291 X->s = ( z < 0 ) ? -1 : 1;
292
293cleanup:
294
295 return( ret );
296}
297
298/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000299 * Get a specific bit
300 */
Paul Bakker6b906e52012-05-08 12:01:43 +0000301int mpi_get_bit( const mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000302{
303 if( X->n * biL <= pos )
304 return( 0 );
305
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200306 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000307}
308
309/*
310 * Set a bit to a specific value of 0 or 1
311 */
312int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
313{
314 int ret = 0;
315 size_t off = pos / biL;
316 size_t idx = pos % biL;
317
318 if( val != 0 && val != 1 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200319 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200320
Paul Bakker2f5947e2011-05-18 15:47:11 +0000321 if( X->n * biL <= pos )
322 {
323 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200324 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000325
326 MPI_CHK( mpi_grow( X, off + 1 ) );
327 }
328
Manuel Pégourié-Gonnard9a4a5ac2013-12-04 18:05:29 +0100329 X->p[off] &= ~( (t_uint) 0x01 << idx );
330 X->p[off] |= (t_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000331
332cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200333
Paul Bakker2f5947e2011-05-18 15:47:11 +0000334 return( ret );
335}
336
337/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000338 * Return the number of least significant bits
339 */
Paul Bakker23986e52011-04-24 08:57:21 +0000340size_t mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000341{
Paul Bakker23986e52011-04-24 08:57:21 +0000342 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000343
344 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000345 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000346 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
347 return( count );
348
349 return( 0 );
350}
351
352/*
353 * Return the number of most significant bits
354 */
Paul Bakker23986e52011-04-24 08:57:21 +0000355size_t mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000356{
Paul Bakker23986e52011-04-24 08:57:21 +0000357 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000358
359 for( i = X->n - 1; i > 0; i-- )
360 if( X->p[i] != 0 )
361 break;
362
Paul Bakker23986e52011-04-24 08:57:21 +0000363 for( j = biL; j > 0; j-- )
364 if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000365 break;
366
Paul Bakker23986e52011-04-24 08:57:21 +0000367 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000368}
369
370/*
371 * Return the total size in bytes
372 */
Paul Bakker23986e52011-04-24 08:57:21 +0000373size_t mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000374{
375 return( ( mpi_msb( X ) + 7 ) >> 3 );
376}
377
378/*
379 * Convert an ASCII character to digit value
380 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000381static int mpi_get_digit( t_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000382{
383 *d = 255;
384
385 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
386 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
387 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
388
Paul Bakkera755ca12011-04-24 09:11:17 +0000389 if( *d >= (t_uint) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000390 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000391
392 return( 0 );
393}
394
395/*
396 * Import from an ASCII string
397 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000398int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000399{
Paul Bakker23986e52011-04-24 08:57:21 +0000400 int ret;
401 size_t i, j, slen, n;
Paul Bakkera755ca12011-04-24 09:11:17 +0000402 t_uint d;
Paul Bakker5121ce52009-01-03 21:22:43 +0000403 mpi T;
404
405 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000406 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000407
Paul Bakker6c591fa2011-05-05 11:49:20 +0000408 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000409
Paul Bakkerff60ee62010-03-16 21:09:09 +0000410 slen = strlen( s );
411
Paul Bakker5121ce52009-01-03 21:22:43 +0000412 if( radix == 16 )
413 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000414 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000415
416 MPI_CHK( mpi_grow( X, n ) );
417 MPI_CHK( mpi_lset( X, 0 ) );
418
Paul Bakker23986e52011-04-24 08:57:21 +0000419 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000420 {
Paul Bakker23986e52011-04-24 08:57:21 +0000421 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000422 {
423 X->s = -1;
424 break;
425 }
426
Paul Bakker23986e52011-04-24 08:57:21 +0000427 MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200428 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000429 }
430 }
431 else
432 {
433 MPI_CHK( mpi_lset( X, 0 ) );
434
Paul Bakkerff60ee62010-03-16 21:09:09 +0000435 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000436 {
437 if( i == 0 && s[i] == '-' )
438 {
439 X->s = -1;
440 continue;
441 }
442
443 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
444 MPI_CHK( mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000445
446 if( X->s == 1 )
447 {
448 MPI_CHK( mpi_add_int( X, &T, d ) );
449 }
450 else
451 {
452 MPI_CHK( mpi_sub_int( X, &T, d ) );
453 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000454 }
455 }
456
457cleanup:
458
Paul Bakker6c591fa2011-05-05 11:49:20 +0000459 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000460
461 return( ret );
462}
463
464/*
465 * Helper to write the digits high-order first
466 */
467static int mpi_write_hlp( mpi *X, int radix, char **p )
468{
469 int ret;
Paul Bakkera755ca12011-04-24 09:11:17 +0000470 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000471
472 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000473 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000474
475 MPI_CHK( mpi_mod_int( &r, X, radix ) );
476 MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
477
478 if( mpi_cmp_int( X, 0 ) != 0 )
479 MPI_CHK( mpi_write_hlp( X, radix, p ) );
480
481 if( r < 10 )
482 *(*p)++ = (char)( r + 0x30 );
483 else
484 *(*p)++ = (char)( r + 0x37 );
485
486cleanup:
487
488 return( ret );
489}
490
491/*
492 * Export into an ASCII string
493 */
Paul Bakker23986e52011-04-24 08:57:21 +0000494int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000495{
Paul Bakker23986e52011-04-24 08:57:21 +0000496 int ret = 0;
497 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000498 char *p;
499 mpi T;
500
501 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000502 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000503
504 n = mpi_msb( X );
505 if( radix >= 4 ) n >>= 1;
506 if( radix >= 16 ) n >>= 1;
507 n += 3;
508
509 if( *slen < n )
510 {
511 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000512 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000513 }
514
515 p = s;
Paul Bakker6c591fa2011-05-05 11:49:20 +0000516 mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000517
518 if( X->s == -1 )
519 *p++ = '-';
520
521 if( radix == 16 )
522 {
Paul Bakker23986e52011-04-24 08:57:21 +0000523 int c;
524 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000525
Paul Bakker23986e52011-04-24 08:57:21 +0000526 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000527 {
Paul Bakker23986e52011-04-24 08:57:21 +0000528 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000529 {
Paul Bakker23986e52011-04-24 08:57:21 +0000530 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000531
Paul Bakker6c343d72014-07-10 14:36:19 +0200532 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000533 continue;
534
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000535 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000536 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000537 k = 1;
538 }
539 }
540 }
541 else
542 {
543 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000544
545 if( T.s == -1 )
546 T.s = 1;
547
Paul Bakker5121ce52009-01-03 21:22:43 +0000548 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
549 }
550
551 *p++ = '\0';
552 *slen = p - s;
553
554cleanup:
555
Paul Bakker6c591fa2011-05-05 11:49:20 +0000556 mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000557
558 return( ret );
559}
560
Paul Bakker335db3f2011-04-25 15:28:35 +0000561#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000562/*
563 * Read X from an opened file
564 */
565int mpi_read_file( mpi *X, int radix, FILE *fin )
566{
Paul Bakkera755ca12011-04-24 09:11:17 +0000567 t_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000568 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000569 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000570 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000571 * Buffer should have space for (short) label and decimal formatted MPI,
572 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000573 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000574 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000575
576 memset( s, 0, sizeof( s ) );
577 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000578 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000579
580 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000581 if( slen == sizeof( s ) - 2 )
582 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
583
Paul Bakker5121ce52009-01-03 21:22:43 +0000584 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
585 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
586
587 p = s + slen;
588 while( --p >= s )
589 if( mpi_get_digit( &d, radix, *p ) != 0 )
590 break;
591
592 return( mpi_read_string( X, radix, p + 1 ) );
593}
594
595/*
596 * Write X into an opened file (or stdout if fout == NULL)
597 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000598int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000599{
Paul Bakker23986e52011-04-24 08:57:21 +0000600 int ret;
601 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000602 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000603 * Buffer should have space for (short) label and decimal formatted MPI,
604 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000605 */
Paul Bakker5531c6d2012-09-26 19:20:46 +0000606 char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000607
608 n = sizeof( s );
609 memset( s, 0, n );
610 n -= 2;
611
Paul Bakker23986e52011-04-24 08:57:21 +0000612 MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000613
614 if( p == NULL ) p = "";
615
616 plen = strlen( p );
617 slen = strlen( s );
618 s[slen++] = '\r';
619 s[slen++] = '\n';
620
621 if( fout != NULL )
622 {
623 if( fwrite( p, 1, plen, fout ) != plen ||
624 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000625 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000626 }
627 else
Paul Bakker7dc4c442014-02-01 22:50:26 +0100628 polarssl_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000629
630cleanup:
631
632 return( ret );
633}
Paul Bakker335db3f2011-04-25 15:28:35 +0000634#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000635
636/*
637 * Import X from unsigned binary data, big endian
638 */
Paul Bakker23986e52011-04-24 08:57:21 +0000639int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000640{
Paul Bakker23986e52011-04-24 08:57:21 +0000641 int ret;
642 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000643
644 for( n = 0; n < buflen; n++ )
645 if( buf[n] != 0 )
646 break;
647
648 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
649 MPI_CHK( mpi_lset( X, 0 ) );
650
Paul Bakker23986e52011-04-24 08:57:21 +0000651 for( i = buflen, j = 0; i > n; i--, j++ )
Paul Bakkera755ca12011-04-24 09:11:17 +0000652 X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000653
654cleanup:
655
656 return( ret );
657}
658
659/*
660 * Export X into unsigned binary data, big endian
661 */
Paul Bakker23986e52011-04-24 08:57:21 +0000662int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000663{
Paul Bakker23986e52011-04-24 08:57:21 +0000664 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000665
666 n = mpi_size( X );
667
668 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000669 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000670
671 memset( buf, 0, buflen );
672
673 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
674 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
675
676 return( 0 );
677}
678
679/*
680 * Left-shift: X <<= count
681 */
Paul Bakker23986e52011-04-24 08:57:21 +0000682int mpi_shift_l( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000683{
Paul Bakker23986e52011-04-24 08:57:21 +0000684 int ret;
685 size_t i, v0, t1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000686 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000687
688 v0 = count / (biL );
689 t1 = count & (biL - 1);
690
691 i = mpi_msb( X ) + count;
692
Paul Bakkerf9688572011-05-05 10:00:45 +0000693 if( X->n * biL < i )
Paul Bakker5121ce52009-01-03 21:22:43 +0000694 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
695
696 ret = 0;
697
698 /*
699 * shift by count / limb_size
700 */
701 if( v0 > 0 )
702 {
Paul Bakker23986e52011-04-24 08:57:21 +0000703 for( i = X->n; i > v0; i-- )
704 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000705
Paul Bakker23986e52011-04-24 08:57:21 +0000706 for( ; i > 0; i-- )
707 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000708 }
709
710 /*
711 * shift by count % limb_size
712 */
713 if( t1 > 0 )
714 {
715 for( i = v0; i < X->n; i++ )
716 {
717 r1 = X->p[i] >> (biL - t1);
718 X->p[i] <<= t1;
719 X->p[i] |= r0;
720 r0 = r1;
721 }
722 }
723
724cleanup:
725
726 return( ret );
727}
728
729/*
730 * Right-shift: X >>= count
731 */
Paul Bakker23986e52011-04-24 08:57:21 +0000732int mpi_shift_r( mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000733{
Paul Bakker23986e52011-04-24 08:57:21 +0000734 size_t i, v0, v1;
Paul Bakkera755ca12011-04-24 09:11:17 +0000735 t_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000736
737 v0 = count / biL;
738 v1 = count & (biL - 1);
739
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100740 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
741 return mpi_lset( X, 0 );
742
Paul Bakker5121ce52009-01-03 21:22:43 +0000743 /*
744 * shift by count / limb_size
745 */
746 if( v0 > 0 )
747 {
748 for( i = 0; i < X->n - v0; i++ )
749 X->p[i] = X->p[i + v0];
750
751 for( ; i < X->n; i++ )
752 X->p[i] = 0;
753 }
754
755 /*
756 * shift by count % limb_size
757 */
758 if( v1 > 0 )
759 {
Paul Bakker23986e52011-04-24 08:57:21 +0000760 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000761 {
Paul Bakker23986e52011-04-24 08:57:21 +0000762 r1 = X->p[i - 1] << (biL - v1);
763 X->p[i - 1] >>= v1;
764 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000765 r0 = r1;
766 }
767 }
768
769 return( 0 );
770}
771
772/*
773 * Compare unsigned values
774 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000775int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000776{
Paul Bakker23986e52011-04-24 08:57:21 +0000777 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000778
Paul Bakker23986e52011-04-24 08:57:21 +0000779 for( i = X->n; i > 0; i-- )
780 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000781 break;
782
Paul Bakker23986e52011-04-24 08:57:21 +0000783 for( j = Y->n; j > 0; j-- )
784 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000785 break;
786
Paul Bakker23986e52011-04-24 08:57:21 +0000787 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000788 return( 0 );
789
790 if( i > j ) return( 1 );
791 if( j > i ) return( -1 );
792
Paul Bakker23986e52011-04-24 08:57:21 +0000793 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000794 {
Paul Bakker23986e52011-04-24 08:57:21 +0000795 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
796 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000797 }
798
799 return( 0 );
800}
801
802/*
803 * Compare signed values
804 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000805int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000806{
Paul Bakker23986e52011-04-24 08:57:21 +0000807 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000808
Paul Bakker23986e52011-04-24 08:57:21 +0000809 for( i = X->n; i > 0; i-- )
810 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000811 break;
812
Paul Bakker23986e52011-04-24 08:57:21 +0000813 for( j = Y->n; j > 0; j-- )
814 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000815 break;
816
Paul Bakker23986e52011-04-24 08:57:21 +0000817 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000818 return( 0 );
819
820 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000821 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000822
823 if( X->s > 0 && Y->s < 0 ) return( 1 );
824 if( Y->s > 0 && X->s < 0 ) return( -1 );
825
Paul Bakker23986e52011-04-24 08:57:21 +0000826 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000827 {
Paul Bakker23986e52011-04-24 08:57:21 +0000828 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
829 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000830 }
831
832 return( 0 );
833}
834
835/*
836 * Compare signed values
837 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000838int mpi_cmp_int( const mpi *X, t_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000839{
840 mpi Y;
Paul Bakkera755ca12011-04-24 09:11:17 +0000841 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000842
843 *p = ( z < 0 ) ? -z : z;
844 Y.s = ( z < 0 ) ? -1 : 1;
845 Y.n = 1;
846 Y.p = p;
847
848 return( mpi_cmp_mpi( X, &Y ) );
849}
850
851/*
852 * Unsigned addition: X = |A| + |B| (HAC 14.7)
853 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000854int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000855{
Paul Bakker23986e52011-04-24 08:57:21 +0000856 int ret;
857 size_t i, j;
Paul Bakkera755ca12011-04-24 09:11:17 +0000858 t_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000859
860 if( X == B )
861 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000862 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000863 }
864
865 if( X != A )
866 MPI_CHK( mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200867
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000868 /*
869 * X should always be positive as a result of unsigned additions.
870 */
871 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000872
Paul Bakker23986e52011-04-24 08:57:21 +0000873 for( j = B->n; j > 0; j-- )
874 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000875 break;
876
Paul Bakker23986e52011-04-24 08:57:21 +0000877 MPI_CHK( mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000878
879 o = B->p; p = X->p; c = 0;
880
Paul Bakker23986e52011-04-24 08:57:21 +0000881 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000882 {
883 *p += c; c = ( *p < c );
884 *p += *o; c += ( *p < *o );
885 }
886
887 while( c != 0 )
888 {
889 if( i >= X->n )
890 {
891 MPI_CHK( mpi_grow( X, i + 1 ) );
892 p = X->p + i;
893 }
894
Paul Bakker2d319fd2012-09-16 21:34:26 +0000895 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000896 }
897
898cleanup:
899
900 return( ret );
901}
902
903/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100904 * Helper for mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000905 */
Paul Bakkera755ca12011-04-24 09:11:17 +0000906static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000907{
Paul Bakker23986e52011-04-24 08:57:21 +0000908 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +0000909 t_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000910
911 for( i = c = 0; i < n; i++, s++, d++ )
912 {
913 z = ( *d < c ); *d -= c;
914 c = ( *d < *s ) + z; *d -= *s;
915 }
916
917 while( c != 0 )
918 {
919 z = ( *d < c ); *d -= c;
920 c = z; i++; d++;
921 }
922}
923
924/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100925 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000926 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000927int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000928{
929 mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000930 int ret;
931 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000932
933 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000934 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000935
Paul Bakker6c591fa2011-05-05 11:49:20 +0000936 mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000937
938 if( X == B )
939 {
940 MPI_CHK( mpi_copy( &TB, B ) );
941 B = &TB;
942 }
943
944 if( X != A )
945 MPI_CHK( mpi_copy( X, A ) );
946
Paul Bakker1ef7a532009-06-20 10:50:55 +0000947 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100948 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000949 */
950 X->s = 1;
951
Paul Bakker5121ce52009-01-03 21:22:43 +0000952 ret = 0;
953
Paul Bakker23986e52011-04-24 08:57:21 +0000954 for( n = B->n; n > 0; n-- )
955 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000956 break;
957
Paul Bakker23986e52011-04-24 08:57:21 +0000958 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000959
960cleanup:
961
Paul Bakker6c591fa2011-05-05 11:49:20 +0000962 mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000963
964 return( ret );
965}
966
967/*
968 * Signed addition: X = A + B
969 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000970int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000971{
972 int ret, s = A->s;
973
974 if( A->s * B->s < 0 )
975 {
976 if( mpi_cmp_abs( A, B ) >= 0 )
977 {
978 MPI_CHK( mpi_sub_abs( X, A, B ) );
979 X->s = s;
980 }
981 else
982 {
983 MPI_CHK( mpi_sub_abs( X, B, A ) );
984 X->s = -s;
985 }
986 }
987 else
988 {
989 MPI_CHK( mpi_add_abs( X, A, B ) );
990 X->s = s;
991 }
992
993cleanup:
994
995 return( ret );
996}
997
998/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100999 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001000 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001001int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001002{
1003 int ret, s = A->s;
1004
1005 if( A->s * B->s > 0 )
1006 {
1007 if( mpi_cmp_abs( A, B ) >= 0 )
1008 {
1009 MPI_CHK( mpi_sub_abs( X, A, B ) );
1010 X->s = s;
1011 }
1012 else
1013 {
1014 MPI_CHK( mpi_sub_abs( X, B, A ) );
1015 X->s = -s;
1016 }
1017 }
1018 else
1019 {
1020 MPI_CHK( mpi_add_abs( X, A, B ) );
1021 X->s = s;
1022 }
1023
1024cleanup:
1025
1026 return( ret );
1027}
1028
1029/*
1030 * Signed addition: X = A + b
1031 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001032int mpi_add_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001033{
1034 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001035 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001036
1037 p[0] = ( b < 0 ) ? -b : b;
1038 _B.s = ( b < 0 ) ? -1 : 1;
1039 _B.n = 1;
1040 _B.p = p;
1041
1042 return( mpi_add_mpi( X, A, &_B ) );
1043}
1044
1045/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001046 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001047 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001048int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001049{
1050 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001051 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001052
1053 p[0] = ( b < 0 ) ? -b : b;
1054 _B.s = ( b < 0 ) ? -1 : 1;
1055 _B.n = 1;
1056 _B.p = p;
1057
1058 return( mpi_sub_mpi( X, A, &_B ) );
1059}
1060
1061/*
1062 * Helper for mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001063 */
1064static
1065#if defined(__APPLE__) && defined(__arm__)
1066/*
1067 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1068 * appears to need this to prevent bad ARM code generation at -O3.
1069 */
1070__attribute__ ((noinline))
1071#endif
1072void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001073{
Paul Bakkera755ca12011-04-24 09:11:17 +00001074 t_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001075
1076#if defined(MULADDC_HUIT)
1077 for( ; i >= 8; i -= 8 )
1078 {
1079 MULADDC_INIT
1080 MULADDC_HUIT
1081 MULADDC_STOP
1082 }
1083
1084 for( ; i > 0; i-- )
1085 {
1086 MULADDC_INIT
1087 MULADDC_CORE
1088 MULADDC_STOP
1089 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001090#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001091 for( ; i >= 16; i -= 16 )
1092 {
1093 MULADDC_INIT
1094 MULADDC_CORE MULADDC_CORE
1095 MULADDC_CORE MULADDC_CORE
1096 MULADDC_CORE MULADDC_CORE
1097 MULADDC_CORE MULADDC_CORE
1098
1099 MULADDC_CORE MULADDC_CORE
1100 MULADDC_CORE MULADDC_CORE
1101 MULADDC_CORE MULADDC_CORE
1102 MULADDC_CORE MULADDC_CORE
1103 MULADDC_STOP
1104 }
1105
1106 for( ; i >= 8; i -= 8 )
1107 {
1108 MULADDC_INIT
1109 MULADDC_CORE MULADDC_CORE
1110 MULADDC_CORE MULADDC_CORE
1111
1112 MULADDC_CORE MULADDC_CORE
1113 MULADDC_CORE MULADDC_CORE
1114 MULADDC_STOP
1115 }
1116
1117 for( ; i > 0; i-- )
1118 {
1119 MULADDC_INIT
1120 MULADDC_CORE
1121 MULADDC_STOP
1122 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001123#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001124
1125 t++;
1126
1127 do {
1128 *d += c; c = ( *d < c ); d++;
1129 }
1130 while( c != 0 );
1131}
1132
1133/*
1134 * Baseline multiplication: X = A * B (HAC 14.12)
1135 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001136int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001137{
Paul Bakker23986e52011-04-24 08:57:21 +00001138 int ret;
1139 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001140 mpi TA, TB;
1141
Paul Bakker6c591fa2011-05-05 11:49:20 +00001142 mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001143
1144 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
1145 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
1146
Paul Bakker23986e52011-04-24 08:57:21 +00001147 for( i = A->n; i > 0; i-- )
1148 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001149 break;
1150
Paul Bakker23986e52011-04-24 08:57:21 +00001151 for( j = B->n; j > 0; j-- )
1152 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001153 break;
1154
Paul Bakker23986e52011-04-24 08:57:21 +00001155 MPI_CHK( mpi_grow( X, i + j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001156 MPI_CHK( mpi_lset( X, 0 ) );
1157
Paul Bakker23986e52011-04-24 08:57:21 +00001158 for( i++; j > 0; j-- )
1159 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001160
1161 X->s = A->s * B->s;
1162
1163cleanup:
1164
Paul Bakker6c591fa2011-05-05 11:49:20 +00001165 mpi_free( &TB ); mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001166
1167 return( ret );
1168}
1169
1170/*
1171 * Baseline multiplication: X = A * b
1172 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001173int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001174{
1175 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001176 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001177
1178 _B.s = 1;
1179 _B.n = 1;
1180 _B.p = p;
1181 p[0] = b;
1182
1183 return( mpi_mul_mpi( X, A, &_B ) );
1184}
1185
1186/*
1187 * Division by mpi: A = Q * B + R (HAC 14.20)
1188 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001189int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001190{
Paul Bakker23986e52011-04-24 08:57:21 +00001191 int ret;
1192 size_t i, n, t, k;
Paul Bakker5121ce52009-01-03 21:22:43 +00001193 mpi X, Y, Z, T1, T2;
1194
1195 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001196 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001197
Paul Bakker6c591fa2011-05-05 11:49:20 +00001198 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
1199 mpi_init( &T1 ); mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001200
1201 if( mpi_cmp_abs( A, B ) < 0 )
1202 {
1203 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1204 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1205 return( 0 );
1206 }
1207
1208 MPI_CHK( mpi_copy( &X, A ) );
1209 MPI_CHK( mpi_copy( &Y, B ) );
1210 X.s = Y.s = 1;
1211
1212 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1213 MPI_CHK( mpi_lset( &Z, 0 ) );
1214 MPI_CHK( mpi_grow( &T1, 2 ) );
1215 MPI_CHK( mpi_grow( &T2, 3 ) );
1216
1217 k = mpi_msb( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001218 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001219 {
1220 k = biL - 1 - k;
1221 MPI_CHK( mpi_shift_l( &X, k ) );
1222 MPI_CHK( mpi_shift_l( &Y, k ) );
1223 }
1224 else k = 0;
1225
1226 n = X.n - 1;
1227 t = Y.n - 1;
Paul Bakker66d5d072014-06-17 16:39:18 +02001228 MPI_CHK( mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001229
1230 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1231 {
1232 Z.p[n - t]++;
Paul Bakker6ea1a952013-12-31 11:16:03 +01001233 MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001234 }
Paul Bakker66d5d072014-06-17 16:39:18 +02001235 MPI_CHK( mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001236
1237 for( i = n; i > t ; i-- )
1238 {
1239 if( X.p[i] >= Y.p[t] )
1240 Z.p[i - t - 1] = ~0;
1241 else
1242 {
Manuel Pégourié-Gonnardbb8661e2014-03-14 09:21:20 +01001243 /*
Manuel Pégourié-Gonnard2eea2922014-03-14 18:23:26 +01001244 * The version of Clang shipped by Apple with Mavericks around
1245 * 2014-03 can't handle 128-bit division properly. Disable
1246 * 128-bits division for this version. Let's be optimistic and
1247 * assume it'll be fixed in the next minor version (next
1248 * patchlevel is probably a bit too optimistic).
Manuel Pégourié-Gonnardbb8661e2014-03-14 09:21:20 +01001249 */
Manuel Pégourié-Gonnard2eea2922014-03-14 18:23:26 +01001250#if defined(POLARSSL_HAVE_UDBL) && \
1251 ! ( defined(__x86_64__) && defined(__APPLE__) && \
1252 defined(__clang_major__) && __clang_major__ == 5 && \
1253 defined(__clang_minor__) && __clang_minor__ == 0 )
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001254 t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001255
Paul Bakkeradb7ce12011-08-23 14:55:55 +00001256 r = (t_udbl) X.p[i] << biL;
1257 r |= (t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001258 r /= Y.p[t];
Paul Bakker66d5d072014-06-17 16:39:18 +02001259 if( r > ( (t_udbl) 1 << biL ) - 1 )
1260 r = ( (t_udbl) 1 << biL ) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001261
Paul Bakkera755ca12011-04-24 09:11:17 +00001262 Z.p[i - t - 1] = (t_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001263#else
1264 /*
1265 * __udiv_qrnnd_c, from gmp/longlong.h
1266 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001267 t_uint q0, q1, r0, r1;
1268 t_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001269
1270 d = Y.p[t];
1271 d0 = ( d << biH ) >> biH;
1272 d1 = ( d >> biH );
1273
1274 q1 = X.p[i] / d1;
1275 r1 = X.p[i] - d1 * q1;
1276 r1 <<= biH;
1277 r1 |= ( X.p[i - 1] >> biH );
1278
1279 m = q1 * d0;
1280 if( r1 < m )
1281 {
1282 q1--, r1 += d;
1283 while( r1 >= d && r1 < m )
1284 q1--, r1 += d;
1285 }
1286 r1 -= m;
1287
1288 q0 = r1 / d1;
1289 r0 = r1 - d1 * q0;
1290 r0 <<= biH;
1291 r0 |= ( X.p[i - 1] << biH ) >> biH;
1292
1293 m = q0 * d0;
1294 if( r0 < m )
1295 {
1296 q0--, r0 += d;
1297 while( r0 >= d && r0 < m )
1298 q0--, r0 += d;
1299 }
1300 r0 -= m;
1301
1302 Z.p[i - t - 1] = ( q1 << biH ) | q0;
Paul Bakkerdb20c102014-06-17 14:34:44 +02001303#endif /* POLARSSL_HAVE_UDBL && !64-bit Apple with Clang 5.0 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001304 }
1305
1306 Z.p[i - t - 1]++;
1307 do
1308 {
1309 Z.p[i - t - 1]--;
1310
1311 MPI_CHK( mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001312 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001313 T1.p[1] = Y.p[t];
1314 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1315
1316 MPI_CHK( mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001317 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1318 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001319 T2.p[2] = X.p[i];
1320 }
1321 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1322
1323 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001324 MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001325 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1326
1327 if( mpi_cmp_int( &X, 0 ) < 0 )
1328 {
1329 MPI_CHK( mpi_copy( &T1, &Y ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001330 MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001331 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1332 Z.p[i - t - 1]--;
1333 }
1334 }
1335
1336 if( Q != NULL )
1337 {
Paul Bakker6ea1a952013-12-31 11:16:03 +01001338 MPI_CHK( mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001339 Q->s = A->s * B->s;
1340 }
1341
1342 if( R != NULL )
1343 {
Paul Bakker6ea1a952013-12-31 11:16:03 +01001344 MPI_CHK( mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001345 X.s = A->s;
Paul Bakker6ea1a952013-12-31 11:16:03 +01001346 MPI_CHK( mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001347
Paul Bakker5121ce52009-01-03 21:22:43 +00001348 if( mpi_cmp_int( R, 0 ) == 0 )
1349 R->s = 1;
1350 }
1351
1352cleanup:
1353
Paul Bakker6c591fa2011-05-05 11:49:20 +00001354 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
1355 mpi_free( &T1 ); mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001356
1357 return( ret );
1358}
1359
1360/*
1361 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001362 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001363int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001364{
1365 mpi _B;
Paul Bakkera755ca12011-04-24 09:11:17 +00001366 t_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001367
1368 p[0] = ( b < 0 ) ? -b : b;
1369 _B.s = ( b < 0 ) ? -1 : 1;
1370 _B.n = 1;
1371 _B.p = p;
1372
1373 return( mpi_div_mpi( Q, R, A, &_B ) );
1374}
1375
1376/*
1377 * Modulo: R = A mod B
1378 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001379int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001380{
1381 int ret;
1382
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001383 if( mpi_cmp_int( B, 0 ) < 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001384 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001385
Paul Bakker5121ce52009-01-03 21:22:43 +00001386 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1387
1388 while( mpi_cmp_int( R, 0 ) < 0 )
1389 MPI_CHK( mpi_add_mpi( R, R, B ) );
1390
1391 while( mpi_cmp_mpi( R, B ) >= 0 )
1392 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1393
1394cleanup:
1395
1396 return( ret );
1397}
1398
1399/*
1400 * Modulo: r = A mod b
1401 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001402int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001403{
Paul Bakker23986e52011-04-24 08:57:21 +00001404 size_t i;
Paul Bakkera755ca12011-04-24 09:11:17 +00001405 t_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001406
1407 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001408 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001409
1410 if( b < 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001411 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001412
1413 /*
1414 * handle trivial cases
1415 */
1416 if( b == 1 )
1417 {
1418 *r = 0;
1419 return( 0 );
1420 }
1421
1422 if( b == 2 )
1423 {
1424 *r = A->p[0] & 1;
1425 return( 0 );
1426 }
1427
1428 /*
1429 * general case
1430 */
Paul Bakker23986e52011-04-24 08:57:21 +00001431 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001432 {
Paul Bakker23986e52011-04-24 08:57:21 +00001433 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001434 y = ( y << biH ) | ( x >> biH );
1435 z = y / b;
1436 y -= z * b;
1437
1438 x <<= biH;
1439 y = ( y << biH ) | ( x >> biH );
1440 z = y / b;
1441 y -= z * b;
1442 }
1443
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001444 /*
1445 * If A is negative, then the current y represents a negative value.
1446 * Flipping it to the positive side.
1447 */
1448 if( A->s < 0 && y != 0 )
1449 y = b - y;
1450
Paul Bakker5121ce52009-01-03 21:22:43 +00001451 *r = y;
1452
1453 return( 0 );
1454}
1455
1456/*
1457 * Fast Montgomery initialization (thanks to Tom St Denis)
1458 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001459static void mpi_montg_init( t_uint *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001460{
Paul Bakkera755ca12011-04-24 09:11:17 +00001461 t_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001462 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001463
1464 x = m0;
1465 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001466
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001467 for( i = biL; i >= 8; i /= 2 )
1468 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001469
1470 *mm = ~x + 1;
1471}
1472
1473/*
1474 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1475 */
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02001476static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm,
1477 const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001478{
Paul Bakker23986e52011-04-24 08:57:21 +00001479 size_t i, n, m;
Paul Bakkera755ca12011-04-24 09:11:17 +00001480 t_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001481
1482 memset( T->p, 0, T->n * ciL );
1483
1484 d = T->p;
1485 n = N->n;
1486 m = ( B->n < n ) ? B->n : n;
1487
1488 for( i = 0; i < n; i++ )
1489 {
1490 /*
1491 * T = (T + u0*B + u1*N) / 2^biL
1492 */
1493 u0 = A->p[i];
1494 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1495
1496 mpi_mul_hlp( m, B->p, d, u0 );
1497 mpi_mul_hlp( n, N->p, d, u1 );
1498
1499 *d++ = u0; d[n + 1] = 0;
1500 }
1501
Paul Bakker66d5d072014-06-17 16:39:18 +02001502 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001503
1504 if( mpi_cmp_abs( A, N ) >= 0 )
1505 mpi_sub_hlp( n, N->p, A->p );
1506 else
1507 /* prevent timing attacks */
1508 mpi_sub_hlp( n, A->p, T->p );
1509}
1510
1511/*
1512 * Montgomery reduction: A = A * R^-1 mod N
1513 */
Paul Bakkera755ca12011-04-24 09:11:17 +00001514static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001515{
Paul Bakkera755ca12011-04-24 09:11:17 +00001516 t_uint z = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001517 mpi U;
1518
Paul Bakker8ddb6452013-02-27 14:56:33 +01001519 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001520 U.p = &z;
1521
1522 mpi_montmul( A, &U, N, mm, T );
1523}
1524
1525/*
1526 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1527 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001528int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001529{
Paul Bakker23986e52011-04-24 08:57:21 +00001530 int ret;
1531 size_t wbits, wsize, one = 1;
1532 size_t i, j, nblimbs;
1533 size_t bufsize, nbits;
Paul Bakkera755ca12011-04-24 09:11:17 +00001534 t_uint ei, mm, state;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001535 mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
1536 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001537
1538 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001539 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001540
Paul Bakkerf6198c12012-05-16 08:02:29 +00001541 if( mpi_cmp_int( E, 0 ) < 0 )
1542 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
1543
1544 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001545 * Init temps and window size
1546 */
1547 mpi_montg_init( &mm, N );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001548 mpi_init( &RR ); mpi_init( &T );
Manuel Pégourié-Gonnardfd6a1912014-01-18 19:05:23 +01001549 mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001550 memset( W, 0, sizeof( W ) );
1551
1552 i = mpi_msb( E );
1553
1554 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1555 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1556
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001557 if( wsize > POLARSSL_MPI_WINDOW_SIZE )
1558 wsize = POLARSSL_MPI_WINDOW_SIZE;
1559
Paul Bakker5121ce52009-01-03 21:22:43 +00001560 j = N->n + 1;
1561 MPI_CHK( mpi_grow( X, j ) );
1562 MPI_CHK( mpi_grow( &W[1], j ) );
1563 MPI_CHK( mpi_grow( &T, j * 2 ) );
1564
1565 /*
Paul Bakker50546922012-05-19 08:40:49 +00001566 * Compensate for negative A (and correct at the end)
1567 */
1568 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001569 if( neg )
1570 {
1571 MPI_CHK( mpi_copy( &Apos, A ) );
1572 Apos.s = 1;
1573 A = &Apos;
1574 }
1575
1576 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001577 * If 1st call, pre-compute R^2 mod N
1578 */
1579 if( _RR == NULL || _RR->p == NULL )
1580 {
1581 MPI_CHK( mpi_lset( &RR, 1 ) );
1582 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1583 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1584
1585 if( _RR != NULL )
1586 memcpy( _RR, &RR, sizeof( mpi ) );
1587 }
1588 else
1589 memcpy( &RR, _RR, sizeof( mpi ) );
1590
1591 /*
1592 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1593 */
1594 if( mpi_cmp_mpi( A, N ) >= 0 )
Paul Bakkerc2024f42014-01-23 20:38:35 +01001595 MPI_CHK( mpi_mod_mpi( &W[1], A, N ) );
1596 else
1597 MPI_CHK( mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001598
1599 mpi_montmul( &W[1], &RR, N, mm, &T );
1600
1601 /*
1602 * X = R^2 * R^-1 mod N = R mod N
1603 */
1604 MPI_CHK( mpi_copy( X, &RR ) );
1605 mpi_montred( X, N, mm, &T );
1606
1607 if( wsize > 1 )
1608 {
1609 /*
1610 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1611 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001612 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001613
1614 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1615 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1616
1617 for( i = 0; i < wsize - 1; i++ )
1618 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001619
Paul Bakker5121ce52009-01-03 21:22:43 +00001620 /*
1621 * W[i] = W[i - 1] * W[1]
1622 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001623 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001624 {
1625 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1626 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1627
1628 mpi_montmul( &W[i], &W[1], N, mm, &T );
1629 }
1630 }
1631
1632 nblimbs = E->n;
1633 bufsize = 0;
1634 nbits = 0;
1635 wbits = 0;
1636 state = 0;
1637
1638 while( 1 )
1639 {
1640 if( bufsize == 0 )
1641 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001642 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001643 break;
1644
Paul Bakker0d7702c2013-10-29 16:18:35 +01001645 nblimbs--;
1646
Paul Bakkera755ca12011-04-24 09:11:17 +00001647 bufsize = sizeof( t_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001648 }
1649
1650 bufsize--;
1651
1652 ei = (E->p[nblimbs] >> bufsize) & 1;
1653
1654 /*
1655 * skip leading 0s
1656 */
1657 if( ei == 0 && state == 0 )
1658 continue;
1659
1660 if( ei == 0 && state == 1 )
1661 {
1662 /*
1663 * out of window, square X
1664 */
1665 mpi_montmul( X, X, N, mm, &T );
1666 continue;
1667 }
1668
1669 /*
1670 * add ei to current window
1671 */
1672 state = 2;
1673
1674 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001675 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001676
1677 if( nbits == wsize )
1678 {
1679 /*
1680 * X = X^wsize R^-1 mod N
1681 */
1682 for( i = 0; i < wsize; i++ )
1683 mpi_montmul( X, X, N, mm, &T );
1684
1685 /*
1686 * X = X * W[wbits] R^-1 mod N
1687 */
1688 mpi_montmul( X, &W[wbits], N, mm, &T );
1689
1690 state--;
1691 nbits = 0;
1692 wbits = 0;
1693 }
1694 }
1695
1696 /*
1697 * process the remaining bits
1698 */
1699 for( i = 0; i < nbits; i++ )
1700 {
1701 mpi_montmul( X, X, N, mm, &T );
1702
1703 wbits <<= 1;
1704
Paul Bakker66d5d072014-06-17 16:39:18 +02001705 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001706 mpi_montmul( X, &W[1], N, mm, &T );
1707 }
1708
1709 /*
1710 * X = A^E * R * R^-1 mod N = A^E mod N
1711 */
1712 mpi_montred( X, N, mm, &T );
1713
Paul Bakkerf6198c12012-05-16 08:02:29 +00001714 if( neg )
1715 {
1716 X->s = -1;
Paul Bakkerc2024f42014-01-23 20:38:35 +01001717 MPI_CHK( mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001718 }
1719
Paul Bakker5121ce52009-01-03 21:22:43 +00001720cleanup:
1721
Paul Bakker66d5d072014-06-17 16:39:18 +02001722 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001723 mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001724
Paul Bakkerf6198c12012-05-16 08:02:29 +00001725 mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001726
Paul Bakker75a28602014-03-31 12:08:17 +02001727 if( _RR == NULL || _RR->p == NULL )
Paul Bakker6c591fa2011-05-05 11:49:20 +00001728 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001729
1730 return( ret );
1731}
1732
Paul Bakker5121ce52009-01-03 21:22:43 +00001733/*
1734 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1735 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001736int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001737{
Paul Bakker23986e52011-04-24 08:57:21 +00001738 int ret;
1739 size_t lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001740 mpi TG, TA, TB;
1741
Paul Bakker6c591fa2011-05-05 11:49:20 +00001742 mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001743
Paul Bakker5121ce52009-01-03 21:22:43 +00001744 MPI_CHK( mpi_copy( &TA, A ) );
1745 MPI_CHK( mpi_copy( &TB, B ) );
1746
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001747 lz = mpi_lsb( &TA );
1748 lzt = mpi_lsb( &TB );
1749
Paul Bakker66d5d072014-06-17 16:39:18 +02001750 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001751 lz = lzt;
1752
1753 MPI_CHK( mpi_shift_r( &TA, lz ) );
1754 MPI_CHK( mpi_shift_r( &TB, lz ) );
1755
Paul Bakker5121ce52009-01-03 21:22:43 +00001756 TA.s = TB.s = 1;
1757
1758 while( mpi_cmp_int( &TA, 0 ) != 0 )
1759 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001760 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1761 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001762
1763 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1764 {
1765 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1766 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1767 }
1768 else
1769 {
1770 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1771 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1772 }
1773 }
1774
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001775 MPI_CHK( mpi_shift_l( &TB, lz ) );
1776 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001777
1778cleanup:
1779
Paul Bakker6c591fa2011-05-05 11:49:20 +00001780 mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001781
1782 return( ret );
1783}
1784
Paul Bakker33dc46b2014-04-30 16:11:39 +02001785/*
1786 * Fill X with size bytes of random.
1787 *
1788 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001789 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001790 * deterministic, eg for tests).
1791 */
Paul Bakkera3d195c2011-11-27 21:07:34 +00001792int mpi_fill_random( mpi *X, size_t size,
1793 int (*f_rng)(void *, unsigned char *, size_t),
1794 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001795{
Paul Bakker23986e52011-04-24 08:57:21 +00001796 int ret;
Paul Bakker33dc46b2014-04-30 16:11:39 +02001797 unsigned char buf[POLARSSL_MPI_MAX_SIZE];
1798
1799 if( size > POLARSSL_MPI_MAX_SIZE )
1800 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001801
Paul Bakker33dc46b2014-04-30 16:11:39 +02001802 MPI_CHK( f_rng( p_rng, buf, size ) );
1803 MPI_CHK( mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001804
1805cleanup:
1806 return( ret );
1807}
1808
Paul Bakker5121ce52009-01-03 21:22:43 +00001809/*
1810 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1811 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001812int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001813{
1814 int ret;
1815 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1816
1817 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001818 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001819
Paul Bakker6c591fa2011-05-05 11:49:20 +00001820 mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
1821 mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
1822 mpi_init( &V1 ); mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001823
1824 MPI_CHK( mpi_gcd( &G, A, N ) );
1825
1826 if( mpi_cmp_int( &G, 1 ) != 0 )
1827 {
Paul Bakker40e46942009-01-03 21:51:57 +00001828 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001829 goto cleanup;
1830 }
1831
1832 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1833 MPI_CHK( mpi_copy( &TU, &TA ) );
1834 MPI_CHK( mpi_copy( &TB, N ) );
1835 MPI_CHK( mpi_copy( &TV, N ) );
1836
1837 MPI_CHK( mpi_lset( &U1, 1 ) );
1838 MPI_CHK( mpi_lset( &U2, 0 ) );
1839 MPI_CHK( mpi_lset( &V1, 0 ) );
1840 MPI_CHK( mpi_lset( &V2, 1 ) );
1841
1842 do
1843 {
1844 while( ( TU.p[0] & 1 ) == 0 )
1845 {
1846 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1847
1848 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1849 {
1850 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1851 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1852 }
1853
1854 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1855 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1856 }
1857
1858 while( ( TV.p[0] & 1 ) == 0 )
1859 {
1860 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1861
1862 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1863 {
1864 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1865 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1866 }
1867
1868 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1869 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1870 }
1871
1872 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1873 {
1874 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1875 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1876 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1877 }
1878 else
1879 {
1880 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1881 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1882 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1883 }
1884 }
1885 while( mpi_cmp_int( &TU, 0 ) != 0 );
1886
1887 while( mpi_cmp_int( &V1, 0 ) < 0 )
1888 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1889
1890 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1891 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1892
1893 MPI_CHK( mpi_copy( X, &V1 ) );
1894
1895cleanup:
1896
Paul Bakker6c591fa2011-05-05 11:49:20 +00001897 mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
1898 mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
1899 mpi_free( &V1 ); mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001900
1901 return( ret );
1902}
1903
Paul Bakkerd9374b02012-11-02 11:02:58 +00001904#if defined(POLARSSL_GENPRIME)
1905
Paul Bakker5121ce52009-01-03 21:22:43 +00001906static const int small_prime[] =
1907{
1908 3, 5, 7, 11, 13, 17, 19, 23,
1909 29, 31, 37, 41, 43, 47, 53, 59,
1910 61, 67, 71, 73, 79, 83, 89, 97,
1911 101, 103, 107, 109, 113, 127, 131, 137,
1912 139, 149, 151, 157, 163, 167, 173, 179,
1913 181, 191, 193, 197, 199, 211, 223, 227,
1914 229, 233, 239, 241, 251, 257, 263, 269,
1915 271, 277, 281, 283, 293, 307, 311, 313,
1916 317, 331, 337, 347, 349, 353, 359, 367,
1917 373, 379, 383, 389, 397, 401, 409, 419,
1918 421, 431, 433, 439, 443, 449, 457, 461,
1919 463, 467, 479, 487, 491, 499, 503, 509,
1920 521, 523, 541, 547, 557, 563, 569, 571,
1921 577, 587, 593, 599, 601, 607, 613, 617,
1922 619, 631, 641, 643, 647, 653, 659, 661,
1923 673, 677, 683, 691, 701, 709, 719, 727,
1924 733, 739, 743, 751, 757, 761, 769, 773,
1925 787, 797, 809, 811, 821, 823, 827, 829,
1926 839, 853, 857, 859, 863, 877, 881, 883,
1927 887, 907, 911, 919, 929, 937, 941, 947,
1928 953, 967, 971, 977, 983, 991, 997, -103
1929};
1930
1931/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001932 * Small divisors test (X must be positive)
1933 *
1934 * Return values:
1935 * 0: no small factor (possible prime, more tests needed)
1936 * 1: certain prime
1937 * POLARSSL_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
1938 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00001939 */
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001940static int mpi_check_small_factors( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00001941{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001942 int ret = 0;
1943 size_t i;
1944 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
Paul Bakker5121ce52009-01-03 21:22:43 +00001946 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001947 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001948
1949 for( i = 0; small_prime[i] > 0; i++ )
1950 {
Paul Bakker5121ce52009-01-03 21:22:43 +00001951 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001952 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001953
1954 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1955
1956 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001957 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001958 }
1959
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001960cleanup:
1961 return( ret );
1962}
1963
1964/*
1965 * Miller-Rabin pseudo-primality test (HAC 4.24)
1966 */
1967static int mpi_miller_rabin( const mpi *X,
1968 int (*f_rng)(void *, unsigned char *, size_t),
1969 void *p_rng )
1970{
1971 int ret;
1972 size_t i, j, n, s;
1973 mpi W, R, T, A, RR;
1974
1975 mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
1976 mpi_init( &RR );
1977
Paul Bakker5121ce52009-01-03 21:22:43 +00001978 /*
1979 * W = |X| - 1
1980 * R = W >> lsb( W )
1981 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001982 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001983 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001984 MPI_CHK( mpi_copy( &R, &W ) );
1985 MPI_CHK( mpi_shift_r( &R, s ) );
1986
1987 i = mpi_msb( X );
1988 /*
1989 * HAC, table 4.4
1990 */
1991 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1992 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1993 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1994
1995 for( i = 0; i < n; i++ )
1996 {
1997 /*
1998 * pick a random A, 1 < A < |X| - 1
1999 */
Paul Bakker901c6562012-04-20 13:25:38 +00002000 MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002001
Paul Bakkerb94081b2011-01-05 15:53:06 +00002002 if( mpi_cmp_mpi( &A, &W ) >= 0 )
2003 {
2004 j = mpi_msb( &A ) - mpi_msb( &W );
2005 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
2006 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002007 A.p[0] |= 3;
2008
2009 /*
2010 * A = A^R mod |X|
2011 */
2012 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
2013
2014 if( mpi_cmp_mpi( &A, &W ) == 0 ||
2015 mpi_cmp_int( &A, 1 ) == 0 )
2016 continue;
2017
2018 j = 1;
2019 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
2020 {
2021 /*
2022 * A = A * A mod |X|
2023 */
2024 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
2025 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
2026
2027 if( mpi_cmp_int( &A, 1 ) == 0 )
2028 break;
2029
2030 j++;
2031 }
2032
2033 /*
2034 * not prime if A != |X| - 1 or A == 1
2035 */
2036 if( mpi_cmp_mpi( &A, &W ) != 0 ||
2037 mpi_cmp_int( &A, 1 ) == 0 )
2038 {
Paul Bakker40e46942009-01-03 21:51:57 +00002039 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002040 break;
2041 }
2042 }
2043
2044cleanup:
Paul Bakker6c591fa2011-05-05 11:49:20 +00002045 mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
2046 mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002047
2048 return( ret );
2049}
2050
2051/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002052 * Pseudo-primality test: small factors, then Miller-Rabin
2053 */
Paul Bakker45f457d2013-11-25 14:26:52 +01002054int mpi_is_prime( mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002055 int (*f_rng)(void *, unsigned char *, size_t),
2056 void *p_rng )
2057{
2058 int ret;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002059 mpi XX;
2060
2061 XX.s = 1;
2062 XX.n = X->n;
2063 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002064
2065 if( mpi_cmp_int( &XX, 0 ) == 0 ||
2066 mpi_cmp_int( &XX, 1 ) == 0 )
2067 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
2068
2069 if( mpi_cmp_int( &XX, 2 ) == 0 )
2070 return( 0 );
2071
2072 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2073 {
2074 if( ret == 1 )
2075 return( 0 );
2076
2077 return( ret );
2078 }
2079
2080 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2081}
2082
2083/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002084 * Prime number generation
2085 */
Paul Bakker23986e52011-04-24 08:57:21 +00002086int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002087 int (*f_rng)(void *, unsigned char *, size_t),
2088 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002089{
Paul Bakker23986e52011-04-24 08:57:21 +00002090 int ret;
2091 size_t k, n;
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002092 t_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002093 mpi Y;
2094
Paul Bakkerfe3256e2011-11-25 12:11:43 +00002095 if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
Paul Bakker40e46942009-01-03 21:51:57 +00002096 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002097
Paul Bakker6c591fa2011-05-05 11:49:20 +00002098 mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002099
2100 n = BITS_TO_LIMBS( nbits );
2101
Paul Bakker901c6562012-04-20 13:25:38 +00002102 MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002103
2104 k = mpi_msb( X );
2105 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
2106 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
2107
2108 X->p[0] |= 3;
2109
2110 if( dh_flag == 0 )
2111 {
2112 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
2113 {
Paul Bakker40e46942009-01-03 21:51:57 +00002114 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002115 goto cleanup;
2116
2117 MPI_CHK( mpi_add_int( X, X, 2 ) );
2118 }
2119 }
2120 else
2121 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002122 /*
2123 * An necessary condition for Y and X = 2Y + 1 to be prime
2124 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2125 * Make sure it is satisfied, while keeping X = 3 mod 4
2126 */
2127 MPI_CHK( mpi_mod_int( &r, X, 3 ) );
2128 if( r == 0 )
2129 MPI_CHK( mpi_add_int( X, X, 8 ) );
2130 else if( r == 1 )
2131 MPI_CHK( mpi_add_int( X, X, 4 ) );
2132
2133 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2134 MPI_CHK( mpi_copy( &Y, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002135 MPI_CHK( mpi_shift_r( &Y, 1 ) );
2136
2137 while( 1 )
2138 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002139 /*
2140 * First, check small factors for X and Y
2141 * before doing Miller-Rabin on any of them
2142 */
2143 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2144 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2145 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2146 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002147 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002148 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002149 }
2150
Paul Bakker40e46942009-01-03 21:51:57 +00002151 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002152 goto cleanup;
2153
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002154 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002155 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002156 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2157 * so up Y by 6 and X by 12.
2158 */
2159 MPI_CHK( mpi_add_int( X, X, 12 ) );
2160 MPI_CHK( mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002161 }
2162 }
2163
2164cleanup:
2165
Paul Bakker6c591fa2011-05-05 11:49:20 +00002166 mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002167
2168 return( ret );
2169}
2170
Manuel Pégourié-Gonnarddf0142b2013-08-22 18:29:07 +02002171#endif /* POLARSSL_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002172
Paul Bakker40e46942009-01-03 21:51:57 +00002173#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002174
Paul Bakker23986e52011-04-24 08:57:21 +00002175#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002176
2177static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2178{
2179 { 693, 609, 21 },
2180 { 1764, 868, 28 },
2181 { 768454923, 542167814, 1 }
2182};
2183
Paul Bakker5121ce52009-01-03 21:22:43 +00002184/*
2185 * Checkup routine
2186 */
2187int mpi_self_test( int verbose )
2188{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002189 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002190 mpi A, E, N, X, Y, U, V;
2191
Paul Bakker6c591fa2011-05-05 11:49:20 +00002192 mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
2193 mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002194
2195 MPI_CHK( mpi_read_string( &A, 16,
2196 "EFE021C2645FD1DC586E69184AF4A31E" \
2197 "D5F53E93B5F123FA41680867BA110131" \
2198 "944FE7952E2517337780CB0DB80E61AA" \
2199 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2200
2201 MPI_CHK( mpi_read_string( &E, 16,
2202 "B2E7EFD37075B9F03FF989C7C5051C20" \
2203 "34D2A323810251127E7BF8625A4F49A5" \
2204 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2205 "5B5C25763222FEFCCFC38B832366C29E" ) );
2206
2207 MPI_CHK( mpi_read_string( &N, 16,
2208 "0066A198186C18C10B2F5ED9B522752A" \
2209 "9830B69916E535C8F047518A889A43A5" \
2210 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2211
2212 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
2213
2214 MPI_CHK( mpi_read_string( &U, 16,
2215 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2216 "9E857EA95A03512E2BAE7391688D264A" \
2217 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2218 "8001B72E848A38CAE1C65F78E56ABDEF" \
2219 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2220 "ECF677152EF804370C1A305CAF3B5BF1" \
2221 "30879B56C61DE584A0F53A2447A51E" ) );
2222
2223 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002224 polarssl_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002225
2226 if( mpi_cmp_mpi( &X, &U ) != 0 )
2227 {
2228 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002229 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002230
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002231 ret = 1;
2232 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002233 }
2234
2235 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002236 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002237
2238 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
2239
2240 MPI_CHK( mpi_read_string( &U, 16,
2241 "256567336059E52CAE22925474705F39A94" ) );
2242
2243 MPI_CHK( mpi_read_string( &V, 16,
2244 "6613F26162223DF488E9CD48CC132C7A" \
2245 "0AC93C701B001B092E4E5B9F73BCD27B" \
2246 "9EE50D0657C77F374E903CDFA4C642" ) );
2247
2248 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002249 polarssl_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002250
2251 if( mpi_cmp_mpi( &X, &U ) != 0 ||
2252 mpi_cmp_mpi( &Y, &V ) != 0 )
2253 {
2254 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002255 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002256
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002257 ret = 1;
2258 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002259 }
2260
2261 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002262 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002263
2264 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2265
2266 MPI_CHK( mpi_read_string( &U, 16,
2267 "36E139AEA55215609D2816998ED020BB" \
2268 "BD96C37890F65171D948E9BC7CBAA4D9" \
2269 "325D24D6A3C12710F10A09FA08AB87" ) );
2270
2271 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002272 polarssl_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002273
2274 if( mpi_cmp_mpi( &X, &U ) != 0 )
2275 {
2276 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002277 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002278
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002279 ret = 1;
2280 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002281 }
2282
2283 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002284 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002285
2286 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
2287
2288 MPI_CHK( mpi_read_string( &U, 16,
2289 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2290 "C3DBA76456363A10869622EAC2DD84EC" \
2291 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2292
2293 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002294 polarssl_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002295
2296 if( mpi_cmp_mpi( &X, &U ) != 0 )
2297 {
2298 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002299 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002300
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002301 ret = 1;
2302 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002303 }
2304
2305 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002306 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002307
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002308 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002309 polarssl_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002310
Paul Bakker66d5d072014-06-17 16:39:18 +02002311 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002312 {
2313 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
Paul Bakker23986e52011-04-24 08:57:21 +00002314 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002315
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002316 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002317
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002318 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2319 {
2320 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002321 polarssl_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002322
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002323 ret = 1;
2324 goto cleanup;
2325 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002326 }
2327
2328 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002329 polarssl_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002330
Paul Bakker5121ce52009-01-03 21:22:43 +00002331cleanup:
2332
2333 if( ret != 0 && verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002334 polarssl_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002335
Paul Bakker6c591fa2011-05-05 11:49:20 +00002336 mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
2337 mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002338
2339 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01002340 polarssl_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002341
2342 return( ret );
2343}
2344
Paul Bakker9af723c2014-05-01 13:03:14 +02002345#endif /* POLARSSL_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
Paul Bakker9af723c2014-05-01 13:03:14 +02002347#endif /* POLARSSL_BIGNUM_C */