blob: 07892c59e8a7c745d4eaeea11159eb2b4533bf05 [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 */
22/*
23 * This MPI implementation is based on:
24 *
25 * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020026 * http://www.stillhq.com/extracted/gnupg-api/mbedtls_mpi/
Paul Bakker5121ce52009-01-03 21:22:43 +000027 * http://math.libtomcrypt.com/files/tommath.pdf
28 */
29
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020030#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000031#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020032#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020033#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020034#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020036#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000038#include "mbedtls/bignum.h"
39#include "mbedtls/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000040
Rich Evans00ab4702015-02-06 13:43:58 +000041#include <string.h>
42
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020043#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000044#include "mbedtls/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>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020048#define mbedtls_printf printf
49#define mbedtls_malloc malloc
50#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020051#endif
52
Paul Bakker34617722014-06-13 17:20:13 +020053/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020055 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
56}
57
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#define ciL (sizeof(mbedtls_mpi_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071void mbedtls_mpi_init( mbedtls_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084void mbedtls_mpi_free( mbedtls_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 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020091 mbedtls_zeroize( X->p, X->n * ciL );
92 mbedtls_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200103int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000104{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200105 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200107 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
108 return( MBEDTLS_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 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200112 if( ( p = mbedtls_malloc( nblimbs * ciL ) ) == NULL )
113 return( MBEDTLS_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 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120 mbedtls_zeroize( X->p, X->n * ciL );
121 mbedtls_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100136{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100138 size_t i;
139
140 /* Actually resize up in this case */
141 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200142 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100143
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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200152 if( ( p = mbedtls_malloc( i * ciL ) ) == NULL )
153 return( MBEDTLS_ERR_MPI_MALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154
155 memset( p, 0, i * ciL );
156
157 if( X->p != NULL )
158 {
159 memcpy( p, X->p, i * ciL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 mbedtls_zeroize( X->p, X->n * ciL );
161 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100162 }
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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_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 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200183 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200184 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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200194 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000195
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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000208{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000210
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211 memcpy( &T, X, sizeof( mbedtls_mpi ) );
212 memcpy( X, Y, sizeof( mbedtls_mpi ) );
213 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000214}
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é-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100222{
223 int ret = 0;
224 size_t i;
225
Pascal Junodb99183d2015-03-11 16:49:45 +0100226 /* make sure assign is 0 or 1 in a time-constant manner */
227 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100228
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229 MBEDTLS_MPI_CHK( mbedtls_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100250{
251 int ret, s;
252 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200253 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100254
255 if( X == Y )
256 return( 0 );
257
Pascal Junodb99183d2015-03-11 16:49:45 +0100258 /* make sure swap is 0 or 1 in a time-constant manner */
259 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100260
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
262 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100263
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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000284{
285 int ret;
286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200287 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000288 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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200301int mbedtls_mpi_get_bit( const mbedtls_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200312int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000313{
314 int ret = 0;
315 size_t off = pos / biL;
316 size_t idx = pos % biL;
317
318 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200319 return( MBEDTLS_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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000327 }
328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200329 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
330 X->p[off] |= (mbedtls_mpi_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200340size_t mbedtls_mpi_lsb( const mbedtls_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355size_t mbedtls_mpi_msb( const mbedtls_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200373size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000374{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200375 return( ( mbedtls_mpi_msb( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000376}
377
378/*
379 * Convert an ASCII character to digit value
380 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381static int mpi_get_digit( mbedtls_mpi_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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389 if( *d >= (mbedtls_mpi_uint) radix )
390 return( MBEDTLS_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398int mbedtls_mpi_read_string( mbedtls_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;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200402 mbedtls_mpi_uint d;
403 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000404
405 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408 mbedtls_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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
417 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000418
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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200427 MBEDTLS_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 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000434
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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200443 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
444 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000445
446 if( X->s == 1 )
447 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200448 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000449 }
450 else
451 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000453 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000454 }
455 }
456
457cleanup:
458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 mbedtls_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000468{
469 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000471
472 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200473 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000474
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200475 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
476 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000477
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200478 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
479 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200494int mbedtls_mpi_write_string( const mbedtls_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;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000500
501 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 n = mbedtls_mpi_msb( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000505 if( radix >= 4 ) n >>= 1;
506 if( radix >= 16 ) n >>= 1;
507 n += 3;
508
509 if( *slen < n )
510 {
511 *slen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000513 }
514
515 p = s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516 mbedtls_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 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000544
545 if( T.s == -1 )
546 T.s = 1;
547
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200548 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000549 }
550
551 *p++ = '\0';
552 *slen = p - s;
553
554cleanup:
555
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200556 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000557
558 return( ret );
559}
560
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200561#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000562/*
563 * Read X from an opened file
564 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000566{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567 mbedtls_mpi_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200574 char s[ MBEDTLS_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 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 return( MBEDTLS_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 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200582 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000583
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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200592 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000593}
594
595/*
596 * Write X into an opened file (or stdout if fout == NULL)
597 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598int mbedtls_mpi_write_file( const char *p, const mbedtls_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200606 char s[ MBEDTLS_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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612 MBEDTLS_MPI_CHK( mbedtls_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 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200625 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000626 }
627 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000629
630cleanup:
631
632 return( ret );
633}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200634#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000635
636/*
637 * Import X from unsigned binary data, big endian
638 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200639int mbedtls_mpi_read_binary( mbedtls_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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
649 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000650
Paul Bakker23986e52011-04-24 08:57:21 +0000651 for( i = buflen, j = 0; i > n; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200652 X->p[j / ciL] |= ((mbedtls_mpi_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662int mbedtls_mpi_write_binary( const mbedtls_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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000667
668 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669 return( MBEDTLS_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682int mbedtls_mpi_shift_l( mbedtls_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;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200686 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000687
688 v0 = count / (biL );
689 t1 = count & (biL - 1);
690
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691 i = mbedtls_mpi_msb( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000692
Paul Bakkerf9688572011-05-05 10:00:45 +0000693 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200694 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000695
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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200732int mbedtls_mpi_shift_r( mbedtls_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;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200735 mbedtls_mpi_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 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100742
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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200775int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200805int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200838int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000839{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200840 mbedtls_mpi Y;
841 mbedtls_mpi_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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200848 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000849}
850
851/*
852 * Unsigned addition: X = |A| + |B| (HAC 14.7)
853 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200854int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_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;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200858 mbedtls_mpi_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000859
860 if( X == B )
861 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200862 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000863 }
864
865 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200866 MBEDTLS_MPI_CHK( mbedtls_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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200877 MBEDTLS_MPI_CHK( mbedtls_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 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200891 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000892 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/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200904 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000905 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200906static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000907{
Paul Bakker23986e52011-04-24 08:57:21 +0000908 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200909 mbedtls_mpi_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200927int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000928{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200929 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000930 int ret;
931 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000932
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200933 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
934 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000935
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200936 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000937
938 if( X == B )
939 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200940 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000941 B = &TB;
942 }
943
944 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200945 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000946
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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200962 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000963
964 return( ret );
965}
966
967/*
968 * Signed addition: X = A + B
969 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200970int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_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 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200976 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000977 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200978 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000979 X->s = s;
980 }
981 else
982 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200983 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000984 X->s = -s;
985 }
986 }
987 else
988 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200989 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000990 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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001001int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_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 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001007 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001008 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001009 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001010 X->s = s;
1011 }
1012 else
1013 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001014 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001015 X->s = -s;
1016 }
1017 }
1018 else
1019 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001020 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001021 X->s = s;
1022 }
1023
1024cleanup:
1025
1026 return( ret );
1027}
1028
1029/*
1030 * Signed addition: X = A + b
1031 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001032int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001033{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001034 mbedtls_mpi _B;
1035 mbedtls_mpi_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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001043}
1044
1045/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001046 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001047 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001048int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001049{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050 mbedtls_mpi _B;
1051 mbedtls_mpi_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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001058 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001059}
1060
1061/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001062 * Helper for mbedtls_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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001072void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001073{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001074 mbedtls_mpi_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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001136int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_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;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001140 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001141
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001142 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001143
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001144 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1145 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001146
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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001155 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1156 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001157
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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001165 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001166
1167 return( ret );
1168}
1169
1170/*
1171 * Baseline multiplication: X = A * b
1172 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001173int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001174{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001175 mbedtls_mpi _B;
1176 mbedtls_mpi_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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001183 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001184}
1185
1186/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001187 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001188 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001189int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_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;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001193 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001194
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001195 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1196 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001197
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001198 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1199 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001201 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001203 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1204 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001205 return( 0 );
1206 }
1207
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001208 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1209 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001210 X.s = Y.s = 1;
1211
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001212 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1213 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1214 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1215 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001216
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001217 k = mbedtls_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;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001221 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1222 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001223 }
1224 else k = 0;
1225
1226 n = X.n - 1;
1227 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001228 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001229
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001230 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001231 {
1232 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001233 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001234 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001235 MBEDTLS_MPI_CHK( mbedtls_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é-Gonnard2cf5a7c2015-04-08 12:49:31 +02001243#if defined(MBEDTLS_HAVE_UDBL)
1244 mbedtls_t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001245
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001246 r = (mbedtls_t_udbl) X.p[i] << biL;
1247 r |= (mbedtls_t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001248 r /= Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001249 if( r > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1250 r = ( (mbedtls_t_udbl) 1 << biL ) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001251
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001252 Z.p[i - t - 1] = (mbedtls_mpi_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001253#else
1254 /*
1255 * __udiv_qrnnd_c, from gmp/longlong.h
1256 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001257 mbedtls_mpi_uint q0, q1, r0, r1;
1258 mbedtls_mpi_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001259
1260 d = Y.p[t];
1261 d0 = ( d << biH ) >> biH;
1262 d1 = ( d >> biH );
1263
1264 q1 = X.p[i] / d1;
1265 r1 = X.p[i] - d1 * q1;
1266 r1 <<= biH;
1267 r1 |= ( X.p[i - 1] >> biH );
1268
1269 m = q1 * d0;
1270 if( r1 < m )
1271 {
1272 q1--, r1 += d;
1273 while( r1 >= d && r1 < m )
1274 q1--, r1 += d;
1275 }
1276 r1 -= m;
1277
1278 q0 = r1 / d1;
1279 r0 = r1 - d1 * q0;
1280 r0 <<= biH;
1281 r0 |= ( X.p[i - 1] << biH ) >> biH;
1282
1283 m = q0 * d0;
1284 if( r0 < m )
1285 {
1286 q0--, r0 += d;
1287 while( r0 >= d && r0 < m )
1288 q0--, r0 += d;
1289 }
1290 r0 -= m;
1291
1292 Z.p[i - t - 1] = ( q1 << biH ) | q0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001293#endif /* MBEDTLS_HAVE_UDBL && !64-bit Apple with Clang 5.0 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001294 }
1295
1296 Z.p[i - t - 1]++;
1297 do
1298 {
1299 Z.p[i - t - 1]--;
1300
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001301 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001302 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001303 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001304 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001305
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001306 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001307 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1308 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001309 T2.p[2] = X.p[i];
1310 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001311 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001312
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001313 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1314 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1315 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001316
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001317 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001318 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001319 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1320 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1321 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001322 Z.p[i - t - 1]--;
1323 }
1324 }
1325
1326 if( Q != NULL )
1327 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001328 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001329 Q->s = A->s * B->s;
1330 }
1331
1332 if( R != NULL )
1333 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001334 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001335 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001338 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001339 R->s = 1;
1340 }
1341
1342cleanup:
1343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001344 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1345 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001346
1347 return( ret );
1348}
1349
1350/*
1351 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001352 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001353int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001354{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001355 mbedtls_mpi _B;
1356 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001357
1358 p[0] = ( b < 0 ) ? -b : b;
1359 _B.s = ( b < 0 ) ? -1 : 1;
1360 _B.n = 1;
1361 _B.p = p;
1362
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001363 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001364}
1365
1366/*
1367 * Modulo: R = A mod B
1368 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001369int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001370{
1371 int ret;
1372
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001373 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1374 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001375
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001376 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001378 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1379 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001381 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1382 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001383
1384cleanup:
1385
1386 return( ret );
1387}
1388
1389/*
1390 * Modulo: r = A mod b
1391 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001393{
Paul Bakker23986e52011-04-24 08:57:21 +00001394 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001395 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001396
1397 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001398 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001399
1400 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001401 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001402
1403 /*
1404 * handle trivial cases
1405 */
1406 if( b == 1 )
1407 {
1408 *r = 0;
1409 return( 0 );
1410 }
1411
1412 if( b == 2 )
1413 {
1414 *r = A->p[0] & 1;
1415 return( 0 );
1416 }
1417
1418 /*
1419 * general case
1420 */
Paul Bakker23986e52011-04-24 08:57:21 +00001421 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001422 {
Paul Bakker23986e52011-04-24 08:57:21 +00001423 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001424 y = ( y << biH ) | ( x >> biH );
1425 z = y / b;
1426 y -= z * b;
1427
1428 x <<= biH;
1429 y = ( y << biH ) | ( x >> biH );
1430 z = y / b;
1431 y -= z * b;
1432 }
1433
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001434 /*
1435 * If A is negative, then the current y represents a negative value.
1436 * Flipping it to the positive side.
1437 */
1438 if( A->s < 0 && y != 0 )
1439 y = b - y;
1440
Paul Bakker5121ce52009-01-03 21:22:43 +00001441 *r = y;
1442
1443 return( 0 );
1444}
1445
1446/*
1447 * Fast Montgomery initialization (thanks to Tom St Denis)
1448 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001449static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001450{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001451 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001452 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001453
1454 x = m0;
1455 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001456
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001457 for( i = biL; i >= 8; i /= 2 )
1458 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001459
1460 *mm = ~x + 1;
1461}
1462
1463/*
1464 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1465 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1467 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001468{
Paul Bakker23986e52011-04-24 08:57:21 +00001469 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001470 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001471
1472 memset( T->p, 0, T->n * ciL );
1473
1474 d = T->p;
1475 n = N->n;
1476 m = ( B->n < n ) ? B->n : n;
1477
1478 for( i = 0; i < n; i++ )
1479 {
1480 /*
1481 * T = (T + u0*B + u1*N) / 2^biL
1482 */
1483 u0 = A->p[i];
1484 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1485
1486 mpi_mul_hlp( m, B->p, d, u0 );
1487 mpi_mul_hlp( n, N->p, d, u1 );
1488
1489 *d++ = u0; d[n + 1] = 0;
1490 }
1491
Paul Bakker66d5d072014-06-17 16:39:18 +02001492 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001493
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001494 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001495 mpi_sub_hlp( n, N->p, A->p );
1496 else
1497 /* prevent timing attacks */
1498 mpi_sub_hlp( n, A->p, T->p );
1499}
1500
1501/*
1502 * Montgomery reduction: A = A * R^-1 mod N
1503 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001504static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001505{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506 mbedtls_mpi_uint z = 1;
1507 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001508
Paul Bakker8ddb6452013-02-27 14:56:33 +01001509 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001510 U.p = &z;
1511
1512 mpi_montmul( A, &U, N, mm, T );
1513}
1514
1515/*
1516 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1517 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001518int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001519{
Paul Bakker23986e52011-04-24 08:57:21 +00001520 int ret;
1521 size_t wbits, wsize, one = 1;
1522 size_t i, j, nblimbs;
1523 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001524 mbedtls_mpi_uint ei, mm, state;
1525 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001526 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001527
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001528 if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
1529 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001530
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001531 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1532 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001533
1534 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001535 * Init temps and window size
1536 */
1537 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001538 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1539 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001540 memset( W, 0, sizeof( W ) );
1541
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001542 i = mbedtls_mpi_msb( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001543
1544 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1545 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1546
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001547 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1548 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001549
Paul Bakker5121ce52009-01-03 21:22:43 +00001550 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001551 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1552 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1553 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001554
1555 /*
Paul Bakker50546922012-05-19 08:40:49 +00001556 * Compensate for negative A (and correct at the end)
1557 */
1558 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001559 if( neg )
1560 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001561 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001562 Apos.s = 1;
1563 A = &Apos;
1564 }
1565
1566 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001567 * If 1st call, pre-compute R^2 mod N
1568 */
1569 if( _RR == NULL || _RR->p == NULL )
1570 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001571 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1572 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1573 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001574
1575 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001576 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001577 }
1578 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001579 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001580
1581 /*
1582 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1583 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001584 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1585 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001586 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001587 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001588
1589 mpi_montmul( &W[1], &RR, N, mm, &T );
1590
1591 /*
1592 * X = R^2 * R^-1 mod N = R mod N
1593 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001594 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001595 mpi_montred( X, N, mm, &T );
1596
1597 if( wsize > 1 )
1598 {
1599 /*
1600 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1601 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001602 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001603
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001604 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1605 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001606
1607 for( i = 0; i < wsize - 1; i++ )
1608 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001609
Paul Bakker5121ce52009-01-03 21:22:43 +00001610 /*
1611 * W[i] = W[i - 1] * W[1]
1612 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001613 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001614 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001615 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1616 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001617
1618 mpi_montmul( &W[i], &W[1], N, mm, &T );
1619 }
1620 }
1621
1622 nblimbs = E->n;
1623 bufsize = 0;
1624 nbits = 0;
1625 wbits = 0;
1626 state = 0;
1627
1628 while( 1 )
1629 {
1630 if( bufsize == 0 )
1631 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001632 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001633 break;
1634
Paul Bakker0d7702c2013-10-29 16:18:35 +01001635 nblimbs--;
1636
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001637 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001638 }
1639
1640 bufsize--;
1641
1642 ei = (E->p[nblimbs] >> bufsize) & 1;
1643
1644 /*
1645 * skip leading 0s
1646 */
1647 if( ei == 0 && state == 0 )
1648 continue;
1649
1650 if( ei == 0 && state == 1 )
1651 {
1652 /*
1653 * out of window, square X
1654 */
1655 mpi_montmul( X, X, N, mm, &T );
1656 continue;
1657 }
1658
1659 /*
1660 * add ei to current window
1661 */
1662 state = 2;
1663
1664 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001665 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001666
1667 if( nbits == wsize )
1668 {
1669 /*
1670 * X = X^wsize R^-1 mod N
1671 */
1672 for( i = 0; i < wsize; i++ )
1673 mpi_montmul( X, X, N, mm, &T );
1674
1675 /*
1676 * X = X * W[wbits] R^-1 mod N
1677 */
1678 mpi_montmul( X, &W[wbits], N, mm, &T );
1679
1680 state--;
1681 nbits = 0;
1682 wbits = 0;
1683 }
1684 }
1685
1686 /*
1687 * process the remaining bits
1688 */
1689 for( i = 0; i < nbits; i++ )
1690 {
1691 mpi_montmul( X, X, N, mm, &T );
1692
1693 wbits <<= 1;
1694
Paul Bakker66d5d072014-06-17 16:39:18 +02001695 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001696 mpi_montmul( X, &W[1], N, mm, &T );
1697 }
1698
1699 /*
1700 * X = A^E * R * R^-1 mod N = A^E mod N
1701 */
1702 mpi_montred( X, N, mm, &T );
1703
Paul Bakkerf6198c12012-05-16 08:02:29 +00001704 if( neg )
1705 {
1706 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001707 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001708 }
1709
Paul Bakker5121ce52009-01-03 21:22:43 +00001710cleanup:
1711
Paul Bakker66d5d072014-06-17 16:39:18 +02001712 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001713 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001714
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001715 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001716
Paul Bakker75a28602014-03-31 12:08:17 +02001717 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001718 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001719
1720 return( ret );
1721}
1722
Paul Bakker5121ce52009-01-03 21:22:43 +00001723/*
1724 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1725 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001726int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001727{
Paul Bakker23986e52011-04-24 08:57:21 +00001728 int ret;
1729 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001730 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001731
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001732 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001733
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001734 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1735 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001736
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001737 lz = mbedtls_mpi_lsb( &TA );
1738 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001739
Paul Bakker66d5d072014-06-17 16:39:18 +02001740 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001741 lz = lzt;
1742
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001743 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1744 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001745
Paul Bakker5121ce52009-01-03 21:22:43 +00001746 TA.s = TB.s = 1;
1747
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001748 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001749 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001750 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1751 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001752
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001753 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001754 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1756 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001757 }
1758 else
1759 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001760 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1761 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001762 }
1763 }
1764
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001765 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1766 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001767
1768cleanup:
1769
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001770 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001771
1772 return( ret );
1773}
1774
Paul Bakker33dc46b2014-04-30 16:11:39 +02001775/*
1776 * Fill X with size bytes of random.
1777 *
1778 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001779 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001780 * deterministic, eg for tests).
1781 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001782int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001783 int (*f_rng)(void *, unsigned char *, size_t),
1784 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001785{
Paul Bakker23986e52011-04-24 08:57:21 +00001786 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001787 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001788
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001789 if( size > MBEDTLS_MPI_MAX_SIZE )
1790 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001791
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001792 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1793 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001794
1795cleanup:
1796 return( ret );
1797}
1798
Paul Bakker5121ce52009-01-03 21:22:43 +00001799/*
1800 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1801 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001802int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001803{
1804 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001805 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001806
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001807 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 )
1808 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001809
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001810 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1811 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1812 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001813
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001814 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001815
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001817 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001818 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001819 goto cleanup;
1820 }
1821
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001822 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1823 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1824 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1825 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001826
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001827 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1828 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1829 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1830 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001831
1832 do
1833 {
1834 while( ( TU.p[0] & 1 ) == 0 )
1835 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001836 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001837
1838 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1839 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001840 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1841 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001842 }
1843
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1845 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846 }
1847
1848 while( ( TV.p[0] & 1 ) == 0 )
1849 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001850 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001851
1852 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1853 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001854 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1855 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001856 }
1857
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001858 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1859 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001860 }
1861
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001862 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001863 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001864 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1865 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1866 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001867 }
1868 else
1869 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001870 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1871 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1872 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001873 }
1874 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001875 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001876
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001877 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1878 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001879
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1881 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001882
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001883 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001884
1885cleanup:
1886
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001887 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1888 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1889 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001890
1891 return( ret );
1892}
1893
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001895
Paul Bakker5121ce52009-01-03 21:22:43 +00001896static const int small_prime[] =
1897{
1898 3, 5, 7, 11, 13, 17, 19, 23,
1899 29, 31, 37, 41, 43, 47, 53, 59,
1900 61, 67, 71, 73, 79, 83, 89, 97,
1901 101, 103, 107, 109, 113, 127, 131, 137,
1902 139, 149, 151, 157, 163, 167, 173, 179,
1903 181, 191, 193, 197, 199, 211, 223, 227,
1904 229, 233, 239, 241, 251, 257, 263, 269,
1905 271, 277, 281, 283, 293, 307, 311, 313,
1906 317, 331, 337, 347, 349, 353, 359, 367,
1907 373, 379, 383, 389, 397, 401, 409, 419,
1908 421, 431, 433, 439, 443, 449, 457, 461,
1909 463, 467, 479, 487, 491, 499, 503, 509,
1910 521, 523, 541, 547, 557, 563, 569, 571,
1911 577, 587, 593, 599, 601, 607, 613, 617,
1912 619, 631, 641, 643, 647, 653, 659, 661,
1913 673, 677, 683, 691, 701, 709, 719, 727,
1914 733, 739, 743, 751, 757, 761, 769, 773,
1915 787, 797, 809, 811, 821, 823, 827, 829,
1916 839, 853, 857, 859, 863, 877, 881, 883,
1917 887, 907, 911, 919, 929, 937, 941, 947,
1918 953, 967, 971, 977, 983, 991, 997, -103
1919};
1920
1921/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001922 * Small divisors test (X must be positive)
1923 *
1924 * Return values:
1925 * 0: no small factor (possible prime, more tests needed)
1926 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001927 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001928 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00001929 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001930static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00001931{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001932 int ret = 0;
1933 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001934 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001935
Paul Bakker5121ce52009-01-03 21:22:43 +00001936 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001937 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001938
1939 for( i = 0; small_prime[i] > 0; i++ )
1940 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001941 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001942 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001943
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001944 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
1946 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001947 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001948 }
1949
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001950cleanup:
1951 return( ret );
1952}
1953
1954/*
1955 * Miller-Rabin pseudo-primality test (HAC 4.24)
1956 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001957static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001958 int (*f_rng)(void *, unsigned char *, size_t),
1959 void *p_rng )
1960{
Pascal Junodb99183d2015-03-11 16:49:45 +01001961 int ret, count;
1962 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001964
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001965 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
1966 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001967
Paul Bakker5121ce52009-01-03 21:22:43 +00001968 /*
1969 * W = |X| - 1
1970 * R = W >> lsb( W )
1971 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001972 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
1973 s = mbedtls_mpi_lsb( &W );
1974 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
1975 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001976
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001977 i = mbedtls_mpi_msb( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00001978 /*
1979 * HAC, table 4.4
1980 */
1981 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1982 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1983 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1984
1985 for( i = 0; i < n; i++ )
1986 {
1987 /*
1988 * pick a random A, 1 < A < |X| - 1
1989 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001990 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001991
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001992 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00001993 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001994 j = mbedtls_mpi_msb( &A ) - mbedtls_mpi_msb( &W );
1995 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00001996 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001997 A.p[0] |= 3;
1998
Pascal Junodb99183d2015-03-11 16:49:45 +01001999 count = 0;
2000 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002001 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002002
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002003 j = mbedtls_mpi_msb( &A );
2004 k = mbedtls_mpi_msb( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002005 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002006 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002007 }
2008
2009 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002010 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002011 }
2012
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002013 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2014 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002015
2016 /*
2017 * A = A^R mod |X|
2018 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002019 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002020
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002021 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2022 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002023 continue;
2024
2025 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002026 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002027 {
2028 /*
2029 * A = A * A mod |X|
2030 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002031 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2032 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002035 break;
2036
2037 j++;
2038 }
2039
2040 /*
2041 * not prime if A != |X| - 1 or A == 1
2042 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002043 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2044 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002045 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002047 break;
2048 }
2049 }
2050
2051cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2053 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002054
2055 return( ret );
2056}
2057
2058/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002059 * Pseudo-primality test: small factors, then Miller-Rabin
2060 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002061int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002062 int (*f_rng)(void *, unsigned char *, size_t),
2063 void *p_rng )
2064{
2065 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002066 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002067
2068 XX.s = 1;
2069 XX.n = X->n;
2070 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002071
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002072 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2073 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2074 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002075
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002077 return( 0 );
2078
2079 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2080 {
2081 if( ret == 1 )
2082 return( 0 );
2083
2084 return( ret );
2085 }
2086
2087 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2088}
2089
2090/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002091 * Prime number generation
2092 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002093int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002094 int (*f_rng)(void *, unsigned char *, size_t),
2095 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002096{
Paul Bakker23986e52011-04-24 08:57:21 +00002097 int ret;
2098 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002099 mbedtls_mpi_uint r;
2100 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002101
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002102 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2103 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002104
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002105 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002106
2107 n = BITS_TO_LIMBS( nbits );
2108
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002109 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002111 k = mbedtls_mpi_msb( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002112 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002113
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002114 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002115
2116 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002117
2118 if( dh_flag == 0 )
2119 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002120 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002121 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002122 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002123 goto cleanup;
2124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002125 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002126 }
2127 }
2128 else
2129 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002130 /*
2131 * An necessary condition for Y and X = 2Y + 1 to be prime
2132 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2133 * Make sure it is satisfied, while keeping X = 3 mod 4
2134 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002135
2136 X->p[0] |= 2;
2137
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002138 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002139 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002140 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002141 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002142 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002143
2144 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2146 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002147
2148 while( 1 )
2149 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002150 /*
2151 * First, check small factors for X and Y
2152 * before doing Miller-Rabin on any of them
2153 */
2154 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2155 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2156 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2157 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002158 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002159 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002160 }
2161
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002162 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002163 goto cleanup;
2164
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002165 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002166 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002167 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2168 * so up Y by 6 and X by 12.
2169 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002170 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2171 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002172 }
2173 }
2174
2175cleanup:
2176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002178
2179 return( ret );
2180}
2181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002182#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002185
Paul Bakker23986e52011-04-24 08:57:21 +00002186#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002187
2188static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2189{
2190 { 693, 609, 21 },
2191 { 1764, 868, 28 },
2192 { 768454923, 542167814, 1 }
2193};
2194
Paul Bakker5121ce52009-01-03 21:22:43 +00002195/*
2196 * Checkup routine
2197 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002199{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002200 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002201 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002202
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002203 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2204 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002205
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002207 "EFE021C2645FD1DC586E69184AF4A31E" \
2208 "D5F53E93B5F123FA41680867BA110131" \
2209 "944FE7952E2517337780CB0DB80E61AA" \
2210 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2211
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002212 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002213 "B2E7EFD37075B9F03FF989C7C5051C20" \
2214 "34D2A323810251127E7BF8625A4F49A5" \
2215 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2216 "5B5C25763222FEFCCFC38B832366C29E" ) );
2217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002218 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002219 "0066A198186C18C10B2F5ED9B522752A" \
2220 "9830B69916E535C8F047518A889A43A5" \
2221 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2222
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002223 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002224
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002225 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002226 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2227 "9E857EA95A03512E2BAE7391688D264A" \
2228 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2229 "8001B72E848A38CAE1C65F78E56ABDEF" \
2230 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2231 "ECF677152EF804370C1A305CAF3B5BF1" \
2232 "30879B56C61DE584A0F53A2447A51E" ) );
2233
2234 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002235 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002236
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002237 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002238 {
2239 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002240 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002241
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002242 ret = 1;
2243 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002244 }
2245
2246 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002247 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002248
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002249 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002250
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002251 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002252 "256567336059E52CAE22925474705F39A94" ) );
2253
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002254 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002255 "6613F26162223DF488E9CD48CC132C7A" \
2256 "0AC93C701B001B092E4E5B9F73BCD27B" \
2257 "9EE50D0657C77F374E903CDFA4C642" ) );
2258
2259 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002260 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002261
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002262 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2263 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002264 {
2265 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002266 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002267
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002268 ret = 1;
2269 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002270 }
2271
2272 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002273 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002274
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002275 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002276
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002277 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002278 "36E139AEA55215609D2816998ED020BB" \
2279 "BD96C37890F65171D948E9BC7CBAA4D9" \
2280 "325D24D6A3C12710F10A09FA08AB87" ) );
2281
2282 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002283 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002284
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002285 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002286 {
2287 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002289
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002290 ret = 1;
2291 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002292 }
2293
2294 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002295 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002296
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002297 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002300 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2301 "C3DBA76456363A10869622EAC2DD84EC" \
2302 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2303
2304 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002305 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002308 {
2309 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002310 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002311
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002312 ret = 1;
2313 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002314 }
2315
2316 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002317 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002318
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002319 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002320 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002321
Paul Bakker66d5d072014-06-17 16:39:18 +02002322 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002323 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002324 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2325 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002327 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002329 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002330 {
2331 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002332 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002333
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002334 ret = 1;
2335 goto cleanup;
2336 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002337 }
2338
2339 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002340 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002341
Paul Bakker5121ce52009-01-03 21:22:43 +00002342cleanup:
2343
2344 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002345 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2348 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002349
2350 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002351 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002352
2353 return( ret );
2354}
2355
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002356#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002358#endif /* MBEDTLS_BIGNUM_C */