blob: 4536a3b8626c890ab324691a7f58d0088754dedd [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000048
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <string.h>
50
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000052#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020053#else
Rich Evans00ab4702015-02-06 13:43:58 +000054#include <stdio.h>
55#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020057#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020059#endif
60
Paul Bakker34617722014-06-13 17:20:13 +020061/* Implementation that should never be optimized out by the compiler */
Alexey Skalozube17a8da2016-01-13 17:19:33 +020062static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) {
Alexey Skalozub3d53f412016-01-13 16:53:40 +020063 volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0;
Paul Bakker34617722014-06-13 17:20:13 +020064}
65
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020066#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000067#define biL (ciL << 3) /* bits in limb */
68#define biH (ciL << 2) /* half limb size */
69
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010070#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
71
Paul Bakker5121ce52009-01-03 21:22:43 +000072/*
73 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020074 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000075 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020076#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
77#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000078
79/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000080 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000081 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000083{
Paul Bakker6c591fa2011-05-05 11:49:20 +000084 if( X == NULL )
85 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000086
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 X->s = 1;
88 X->n = 0;
89 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000090}
91
92/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000094 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020095void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000096{
Paul Bakker6c591fa2011-05-05 11:49:20 +000097 if( X == NULL )
98 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000099
Paul Bakker6c591fa2011-05-05 11:49:20 +0000100 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000101 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200102 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200103 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000104 }
105
Paul Bakker6c591fa2011-05-05 11:49:20 +0000106 X->s = 1;
107 X->n = 0;
108 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000109}
110
111/*
112 * Enlarge to the specified number of limbs
113 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200114int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000115{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000117
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200118 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200119 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000120
Paul Bakker5121ce52009-01-03 21:22:43 +0000121 if( X->n < nblimbs )
122 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200123 if( ( p = mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200124 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000125
Paul Bakker5121ce52009-01-03 21:22:43 +0000126 if( X->p != NULL )
127 {
128 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200129 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000131 }
132
133 X->n = nblimbs;
134 X->p = p;
135 }
136
137 return( 0 );
138}
139
140/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100141 * Resize down as much as possible,
142 * while keeping at least the specified number of limbs
143 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100145{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100147 size_t i;
148
149 /* Actually resize up in this case */
150 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152
153 for( i = X->n - 1; i > 0; i-- )
154 if( X->p[i] != 0 )
155 break;
156 i++;
157
158 if( i < nblimbs )
159 i = nblimbs;
160
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200161 if( ( p = mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200162 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100164 if( X->p != NULL )
165 {
166 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200167 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100169 }
170
171 X->n = i;
172 X->p = p;
173
174 return( 0 );
175}
176
177/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000178 * Copy the contents of Y into X
179 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000181{
Paul Bakker23986e52011-04-24 08:57:21 +0000182 int ret;
183 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000184
185 if( X == Y )
186 return( 0 );
187
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200188 if( Y->p == NULL )
189 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200191 return( 0 );
192 }
193
Paul Bakker5121ce52009-01-03 21:22:43 +0000194 for( i = Y->n - 1; i > 0; i-- )
195 if( Y->p[i] != 0 )
196 break;
197 i++;
198
199 X->s = Y->s;
200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200201 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000202
203 memset( X->p, 0, X->n * ciL );
204 memcpy( X->p, Y->p, i * ciL );
205
206cleanup:
207
208 return( ret );
209}
210
211/*
212 * Swap the contents of X and Y
213 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200214void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000215{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218 memcpy( &T, X, sizeof( mbedtls_mpi ) );
219 memcpy( X, Y, sizeof( mbedtls_mpi ) );
220 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000221}
222
223/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100224 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100225 * about whether the assignment was made or not.
226 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100227 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100229{
230 int ret = 0;
231 size_t i;
232
Pascal Junodb99183d2015-03-11 16:49:45 +0100233 /* make sure assign is 0 or 1 in a time-constant manner */
234 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100235
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100237
Paul Bakker66d5d072014-06-17 16:39:18 +0200238 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100239
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100240 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200241 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100242
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100243 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200244 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100245
246cleanup:
247 return( ret );
248}
249
250/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100251 * Conditionally swap X and Y, without leaking information
252 * about whether the swap was made or not.
253 * Here it is not ok to simply swap the pointers, which whould lead to
254 * different memory access patterns when X and Y are used afterwards.
255 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100257{
258 int ret, s;
259 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100261
262 if( X == Y )
263 return( 0 );
264
Pascal Junodb99183d2015-03-11 16:49:45 +0100265 /* make sure swap is 0 or 1 in a time-constant manner */
266 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
269 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100270
271 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200272 X->s = X->s * ( 1 - swap ) + Y->s * swap;
273 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274
275
276 for( i = 0; i < X->n; i++ )
277 {
278 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200279 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
280 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100281 }
282
283cleanup:
284 return( ret );
285}
286
287/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000288 * Set value from integer
289 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200290int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000291{
292 int ret;
293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000295 memset( X->p, 0, X->n * ciL );
296
297 X->p[0] = ( z < 0 ) ? -z : z;
298 X->s = ( z < 0 ) ? -1 : 1;
299
300cleanup:
301
302 return( ret );
303}
304
305/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000306 * Get a specific bit
307 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000309{
310 if( X->n * biL <= pos )
311 return( 0 );
312
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200313 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000314}
315
316/*
317 * Set a bit to a specific value of 0 or 1
318 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200319int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000320{
321 int ret = 0;
322 size_t off = pos / biL;
323 size_t idx = pos % biL;
324
325 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200327
Paul Bakker2f5947e2011-05-18 15:47:11 +0000328 if( X->n * biL <= pos )
329 {
330 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200331 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200333 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000334 }
335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
337 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338
339cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200340
Paul Bakker2f5947e2011-05-18 15:47:11 +0000341 return( ret );
342}
343
344/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200345 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000346 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000348{
Paul Bakker23986e52011-04-24 08:57:21 +0000349 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000350
351 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000352 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000353 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
354 return( count );
355
356 return( 0 );
357}
358
359/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000360 * Count leading zero bits in a given integer
361 */
362static size_t mbedtls_clz( const mbedtls_mpi_uint x )
363{
364 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100365 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000366
367 for( j = 0; j < biL; j++ )
368 {
369 if( x & mask ) break;
370
371 mask >>= 1;
372 }
373
374 return j;
375}
376
377/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200378 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200380size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000381{
Paul Bakker23986e52011-04-24 08:57:21 +0000382 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000383
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200384 if( X->n == 0 )
385 return( 0 );
386
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 for( i = X->n - 1; i > 0; i-- )
388 if( X->p[i] != 0 )
389 break;
390
Simon Butcher15b15d12015-11-26 19:35:03 +0000391 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000392
Paul Bakker23986e52011-04-24 08:57:21 +0000393 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000394}
395
396/*
397 * Return the total size in bytes
398 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000400{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200401 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000402}
403
404/*
405 * Convert an ASCII character to digit value
406 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000408{
409 *d = 255;
410
411 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
412 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
413 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
414
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415 if( *d >= (mbedtls_mpi_uint) radix )
416 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
418 return( 0 );
419}
420
421/*
422 * Import from an ASCII string
423 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000425{
Paul Bakker23986e52011-04-24 08:57:21 +0000426 int ret;
427 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 mbedtls_mpi_uint d;
429 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000430
431 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000435
Paul Bakkerff60ee62010-03-16 21:09:09 +0000436 slen = strlen( s );
437
Paul Bakker5121ce52009-01-03 21:22:43 +0000438 if( radix == 16 )
439 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100440 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200441 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
442
Paul Bakkerff60ee62010-03-16 21:09:09 +0000443 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
446 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000447
Paul Bakker23986e52011-04-24 08:57:21 +0000448 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000449 {
Paul Bakker23986e52011-04-24 08:57:21 +0000450 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000451 {
452 X->s = -1;
453 break;
454 }
455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200457 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 }
459 }
460 else
461 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000463
Paul Bakkerff60ee62010-03-16 21:09:09 +0000464 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000465 {
466 if( i == 0 && s[i] == '-' )
467 {
468 X->s = -1;
469 continue;
470 }
471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
473 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000474
475 if( X->s == 1 )
476 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000478 }
479 else
480 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000482 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000483 }
484 }
485
486cleanup:
487
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200488 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000489
490 return( ret );
491}
492
493/*
494 * Helper to write the digits high-order first
495 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000497{
498 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 mbedtls_mpi_uint r;
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 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
505 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
508 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000509
510 if( r < 10 )
511 *(*p)++ = (char)( r + 0x30 );
512 else
513 *(*p)++ = (char)( r + 0x37 );
514
515cleanup:
516
517 return( ret );
518}
519
520/*
521 * Export into an ASCII string
522 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100523int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
524 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000525{
Paul Bakker23986e52011-04-24 08:57:21 +0000526 int ret = 0;
527 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000528 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000530
531 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000533
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200534 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000535 if( radix >= 4 ) n >>= 1;
536 if( radix >= 16 ) n >>= 1;
537 n += 3;
538
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100539 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000540 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100541 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000543 }
544
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100545 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000547
548 if( X->s == -1 )
549 *p++ = '-';
550
551 if( radix == 16 )
552 {
Paul Bakker23986e52011-04-24 08:57:21 +0000553 int c;
554 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000555
Paul Bakker23986e52011-04-24 08:57:21 +0000556 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000557 {
Paul Bakker23986e52011-04-24 08:57:21 +0000558 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000559 {
Paul Bakker23986e52011-04-24 08:57:21 +0000560 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000561
Paul Bakker6c343d72014-07-10 14:36:19 +0200562 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000563 continue;
564
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000565 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000566 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000567 k = 1;
568 }
569 }
570 }
571 else
572 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000574
575 if( T.s == -1 )
576 T.s = 1;
577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000579 }
580
581 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100582 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000583
584cleanup:
585
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000587
588 return( ret );
589}
590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000592/*
593 * Read X from an opened file
594 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200595int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000596{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000598 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000599 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000600 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000601 * Buffer should have space for (short) label and decimal formatted MPI,
602 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000603 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000605
606 memset( s, 0, sizeof( s ) );
607 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000609
610 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000611 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000613
Paul Bakker5121ce52009-01-03 21:22:43 +0000614 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
615 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
616
617 p = s + slen;
618 while( --p >= s )
619 if( mpi_get_digit( &d, radix, *p ) != 0 )
620 break;
621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000623}
624
625/*
626 * Write X into an opened file (or stdout if fout == NULL)
627 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000629{
Paul Bakker23986e52011-04-24 08:57:21 +0000630 int ret;
631 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000632 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000633 * Buffer should have space for (short) label and decimal formatted MPI,
634 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000635 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200636 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000637
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100638 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000639
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100640 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000641
642 if( p == NULL ) p = "";
643
644 plen = strlen( p );
645 slen = strlen( s );
646 s[slen++] = '\r';
647 s[slen++] = '\n';
648
649 if( fout != NULL )
650 {
651 if( fwrite( p, 1, plen, fout ) != plen ||
652 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000654 }
655 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000657
658cleanup:
659
660 return( ret );
661}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000663
664/*
665 * Import X from unsigned binary data, big endian
666 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000668{
Paul Bakker23986e52011-04-24 08:57:21 +0000669 int ret;
670 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000671
672 for( n = 0; n < buflen; n++ )
673 if( buf[n] != 0 )
674 break;
675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
677 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000678
Paul Bakker23986e52011-04-24 08:57:21 +0000679 for( i = buflen, j = 0; i > n; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000681
682cleanup:
683
684 return( ret );
685}
686
687/*
688 * Export X into unsigned binary data, big endian
689 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000691{
Paul Bakker23986e52011-04-24 08:57:21 +0000692 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000693
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200694 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000695
696 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
699 memset( buf, 0, buflen );
700
701 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
702 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
703
704 return( 0 );
705}
706
707/*
708 * Left-shift: X <<= count
709 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000711{
Paul Bakker23986e52011-04-24 08:57:21 +0000712 int ret;
713 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000715
716 v0 = count / (biL );
717 t1 = count & (biL - 1);
718
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200719 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000720
Paul Bakkerf9688572011-05-05 10:00:45 +0000721 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000723
724 ret = 0;
725
726 /*
727 * shift by count / limb_size
728 */
729 if( v0 > 0 )
730 {
Paul Bakker23986e52011-04-24 08:57:21 +0000731 for( i = X->n; i > v0; i-- )
732 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000733
Paul Bakker23986e52011-04-24 08:57:21 +0000734 for( ; i > 0; i-- )
735 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000736 }
737
738 /*
739 * shift by count % limb_size
740 */
741 if( t1 > 0 )
742 {
743 for( i = v0; i < X->n; i++ )
744 {
745 r1 = X->p[i] >> (biL - t1);
746 X->p[i] <<= t1;
747 X->p[i] |= r0;
748 r0 = r1;
749 }
750 }
751
752cleanup:
753
754 return( ret );
755}
756
757/*
758 * Right-shift: X >>= count
759 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200760int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000761{
Paul Bakker23986e52011-04-24 08:57:21 +0000762 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200763 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000764
765 v0 = count / biL;
766 v1 = count & (biL - 1);
767
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100768 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200769 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100770
Paul Bakker5121ce52009-01-03 21:22:43 +0000771 /*
772 * shift by count / limb_size
773 */
774 if( v0 > 0 )
775 {
776 for( i = 0; i < X->n - v0; i++ )
777 X->p[i] = X->p[i + v0];
778
779 for( ; i < X->n; i++ )
780 X->p[i] = 0;
781 }
782
783 /*
784 * shift by count % limb_size
785 */
786 if( v1 > 0 )
787 {
Paul Bakker23986e52011-04-24 08:57:21 +0000788 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000789 {
Paul Bakker23986e52011-04-24 08:57:21 +0000790 r1 = X->p[i - 1] << (biL - v1);
791 X->p[i - 1] >>= v1;
792 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000793 r0 = r1;
794 }
795 }
796
797 return( 0 );
798}
799
800/*
801 * Compare unsigned values
802 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200803int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000804{
Paul Bakker23986e52011-04-24 08:57:21 +0000805 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000806
Paul Bakker23986e52011-04-24 08:57:21 +0000807 for( i = X->n; i > 0; i-- )
808 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000809 break;
810
Paul Bakker23986e52011-04-24 08:57:21 +0000811 for( j = Y->n; j > 0; j-- )
812 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000813 break;
814
Paul Bakker23986e52011-04-24 08:57:21 +0000815 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000816 return( 0 );
817
818 if( i > j ) return( 1 );
819 if( j > i ) return( -1 );
820
Paul Bakker23986e52011-04-24 08:57:21 +0000821 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000822 {
Paul Bakker23986e52011-04-24 08:57:21 +0000823 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
824 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000825 }
826
827 return( 0 );
828}
829
830/*
831 * Compare signed values
832 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200833int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000834{
Paul Bakker23986e52011-04-24 08:57:21 +0000835 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000836
Paul Bakker23986e52011-04-24 08:57:21 +0000837 for( i = X->n; i > 0; i-- )
838 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000839 break;
840
Paul Bakker23986e52011-04-24 08:57:21 +0000841 for( j = Y->n; j > 0; j-- )
842 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000843 break;
844
Paul Bakker23986e52011-04-24 08:57:21 +0000845 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000846 return( 0 );
847
848 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000849 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000850
851 if( X->s > 0 && Y->s < 0 ) return( 1 );
852 if( Y->s > 0 && X->s < 0 ) return( -1 );
853
Paul Bakker23986e52011-04-24 08:57:21 +0000854 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000855 {
Paul Bakker23986e52011-04-24 08:57:21 +0000856 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
857 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000858 }
859
860 return( 0 );
861}
862
863/*
864 * Compare signed values
865 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200866int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000867{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200868 mbedtls_mpi Y;
869 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000870
871 *p = ( z < 0 ) ? -z : z;
872 Y.s = ( z < 0 ) ? -1 : 1;
873 Y.n = 1;
874 Y.p = p;
875
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200876 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000877}
878
879/*
880 * Unsigned addition: X = |A| + |B| (HAC 14.7)
881 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200882int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000883{
Paul Bakker23986e52011-04-24 08:57:21 +0000884 int ret;
885 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100886 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000887
888 if( X == B )
889 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200890 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000891 }
892
893 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200894 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200895
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000896 /*
897 * X should always be positive as a result of unsigned additions.
898 */
899 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000900
Paul Bakker23986e52011-04-24 08:57:21 +0000901 for( j = B->n; j > 0; j-- )
902 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000903 break;
904
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200905 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000906
907 o = B->p; p = X->p; c = 0;
908
Janos Follath6c922682015-10-30 17:43:11 +0100909 /*
910 * tmp is used because it might happen that p == o
911 */
Paul Bakker23986e52011-04-24 08:57:21 +0000912 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000913 {
Janos Follath6c922682015-10-30 17:43:11 +0100914 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000915 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100916 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000917 }
918
919 while( c != 0 )
920 {
921 if( i >= X->n )
922 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200923 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000924 p = X->p + i;
925 }
926
Paul Bakker2d319fd2012-09-16 21:34:26 +0000927 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000928 }
929
930cleanup:
931
932 return( ret );
933}
934
935/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200936 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000937 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200938static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000939{
Paul Bakker23986e52011-04-24 08:57:21 +0000940 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000942
943 for( i = c = 0; i < n; i++, s++, d++ )
944 {
945 z = ( *d < c ); *d -= c;
946 c = ( *d < *s ) + z; *d -= *s;
947 }
948
949 while( c != 0 )
950 {
951 z = ( *d < c ); *d -= c;
952 c = z; i++; d++;
953 }
954}
955
956/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100957 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000958 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200959int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000960{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200961 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000962 int ret;
963 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000964
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200965 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
966 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000967
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200968 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000969
970 if( X == B )
971 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200972 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000973 B = &TB;
974 }
975
976 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000978
Paul Bakker1ef7a532009-06-20 10:50:55 +0000979 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100980 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000981 */
982 X->s = 1;
983
Paul Bakker5121ce52009-01-03 21:22:43 +0000984 ret = 0;
985
Paul Bakker23986e52011-04-24 08:57:21 +0000986 for( n = B->n; n > 0; n-- )
987 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000988 break;
989
Paul Bakker23986e52011-04-24 08:57:21 +0000990 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000991
992cleanup:
993
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200994 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000995
996 return( ret );
997}
998
999/*
1000 * Signed addition: X = A + B
1001 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001002int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001003{
1004 int ret, s = A->s;
1005
1006 if( A->s * B->s < 0 )
1007 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001008 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001009 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001010 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001011 X->s = s;
1012 }
1013 else
1014 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001015 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001016 X->s = -s;
1017 }
1018 }
1019 else
1020 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001021 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001022 X->s = s;
1023 }
1024
1025cleanup:
1026
1027 return( ret );
1028}
1029
1030/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001031 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001032 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001033int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001034{
1035 int ret, s = A->s;
1036
1037 if( A->s * B->s > 0 )
1038 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001039 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001040 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001041 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001042 X->s = s;
1043 }
1044 else
1045 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001046 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001047 X->s = -s;
1048 }
1049 }
1050 else
1051 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001052 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001053 X->s = s;
1054 }
1055
1056cleanup:
1057
1058 return( ret );
1059}
1060
1061/*
1062 * Signed addition: X = A + b
1063 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001064int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001065{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001066 mbedtls_mpi _B;
1067 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001068
1069 p[0] = ( b < 0 ) ? -b : b;
1070 _B.s = ( b < 0 ) ? -1 : 1;
1071 _B.n = 1;
1072 _B.p = p;
1073
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001074 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001075}
1076
1077/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001078 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001079 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001080int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001081{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001082 mbedtls_mpi _B;
1083 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001084
1085 p[0] = ( b < 0 ) ? -b : b;
1086 _B.s = ( b < 0 ) ? -1 : 1;
1087 _B.n = 1;
1088 _B.p = p;
1089
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001090 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001091}
1092
1093/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001094 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001095 */
1096static
1097#if defined(__APPLE__) && defined(__arm__)
1098/*
1099 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1100 * appears to need this to prevent bad ARM code generation at -O3.
1101 */
1102__attribute__ ((noinline))
1103#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001104void 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 +00001105{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001106 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001107
1108#if defined(MULADDC_HUIT)
1109 for( ; i >= 8; i -= 8 )
1110 {
1111 MULADDC_INIT
1112 MULADDC_HUIT
1113 MULADDC_STOP
1114 }
1115
1116 for( ; i > 0; i-- )
1117 {
1118 MULADDC_INIT
1119 MULADDC_CORE
1120 MULADDC_STOP
1121 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001122#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001123 for( ; i >= 16; i -= 16 )
1124 {
1125 MULADDC_INIT
1126 MULADDC_CORE MULADDC_CORE
1127 MULADDC_CORE MULADDC_CORE
1128 MULADDC_CORE MULADDC_CORE
1129 MULADDC_CORE MULADDC_CORE
1130
1131 MULADDC_CORE MULADDC_CORE
1132 MULADDC_CORE MULADDC_CORE
1133 MULADDC_CORE MULADDC_CORE
1134 MULADDC_CORE MULADDC_CORE
1135 MULADDC_STOP
1136 }
1137
1138 for( ; i >= 8; i -= 8 )
1139 {
1140 MULADDC_INIT
1141 MULADDC_CORE MULADDC_CORE
1142 MULADDC_CORE MULADDC_CORE
1143
1144 MULADDC_CORE MULADDC_CORE
1145 MULADDC_CORE MULADDC_CORE
1146 MULADDC_STOP
1147 }
1148
1149 for( ; i > 0; i-- )
1150 {
1151 MULADDC_INIT
1152 MULADDC_CORE
1153 MULADDC_STOP
1154 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001155#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001156
1157 t++;
1158
1159 do {
1160 *d += c; c = ( *d < c ); d++;
1161 }
1162 while( c != 0 );
1163}
1164
1165/*
1166 * Baseline multiplication: X = A * B (HAC 14.12)
1167 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001168int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001169{
Paul Bakker23986e52011-04-24 08:57:21 +00001170 int ret;
1171 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001172 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001173
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001174 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001175
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001176 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1177 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001178
Paul Bakker23986e52011-04-24 08:57:21 +00001179 for( i = A->n; i > 0; i-- )
1180 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001181 break;
1182
Paul Bakker23986e52011-04-24 08:57:21 +00001183 for( j = B->n; j > 0; j-- )
1184 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001185 break;
1186
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001187 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1188 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001189
Paul Bakker23986e52011-04-24 08:57:21 +00001190 for( i++; j > 0; j-- )
1191 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001192
1193 X->s = A->s * B->s;
1194
1195cleanup:
1196
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001197 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001198
1199 return( ret );
1200}
1201
1202/*
1203 * Baseline multiplication: X = A * b
1204 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001205int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001206{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001207 mbedtls_mpi _B;
1208 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001209
1210 _B.s = 1;
1211 _B.n = 1;
1212 _B.p = p;
1213 p[0] = b;
1214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001215 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001216}
1217
1218/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001219 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1220 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001221 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001222static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1223 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001224{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001225#if defined(MBEDTLS_HAVE_UDBL)
1226 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001227#else
Simon Butcher9803d072016-01-03 00:24:34 +00001228 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1229 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001230 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1231 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001232 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001233#endif
1234
Simon Butcher15b15d12015-11-26 19:35:03 +00001235 /*
1236 * Check for overflow
1237 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001238 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001239 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001240 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001241
Simon Butcherf5ba0452015-12-27 23:01:55 +00001242 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001243 }
1244
1245#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001246 dividend = (mbedtls_t_udbl) u1 << biL;
1247 dividend |= (mbedtls_t_udbl) u0;
1248 quotient = dividend / d;
1249 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1250 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1251
1252 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001253 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001254
1255 return (mbedtls_mpi_uint) quotient;
1256#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001257
1258 /*
1259 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1260 * Vol. 2 - Seminumerical Algorithms, Knuth
1261 */
1262
1263 /*
1264 * Normalize the divisor, d, and dividend, u0, u1
1265 */
1266 s = mbedtls_clz( d );
1267 d = d << s;
1268
1269 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001270 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001271 u0 = u0 << s;
1272
1273 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001274 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001275
1276 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001277 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001278
1279 /*
1280 * Find the first quotient and remainder
1281 */
1282 q1 = u1 / d1;
1283 r0 = u1 - d1 * q1;
1284
1285 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1286 {
1287 q1 -= 1;
1288 r0 += d1;
1289
1290 if ( r0 >= radix ) break;
1291 }
1292
Simon Butcherf5ba0452015-12-27 23:01:55 +00001293 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001294 q0 = rAX / d1;
1295 r0 = rAX - q0 * d1;
1296
1297 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1298 {
1299 q0 -= 1;
1300 r0 += d1;
1301
1302 if ( r0 >= radix ) break;
1303 }
1304
1305 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001306 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001307
1308 quotient = q1 * radix + q0;
1309
1310 return quotient;
1311#endif
1312}
1313
1314/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001315 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001316 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001317int 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 +00001318{
Paul Bakker23986e52011-04-24 08:57:21 +00001319 int ret;
1320 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001321 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001322
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001323 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1324 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001326 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1327 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001329 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001330 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001331 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1332 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001333 return( 0 );
1334 }
1335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1337 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001338 X.s = Y.s = 1;
1339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001340 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1341 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1342 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1343 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001344
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001345 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001346 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001347 {
1348 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001349 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1350 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001351 }
1352 else k = 0;
1353
1354 n = X.n - 1;
1355 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001356 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001358 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001359 {
1360 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001361 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001362 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001363 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001364
1365 for( i = n; i > t ; i-- )
1366 {
1367 if( X.p[i] >= Y.p[t] )
1368 Z.p[i - t - 1] = ~0;
1369 else
1370 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001371 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1372 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001373 }
1374
1375 Z.p[i - t - 1]++;
1376 do
1377 {
1378 Z.p[i - t - 1]--;
1379
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001380 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001381 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001382 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001383 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001385 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001386 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1387 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001388 T2.p[2] = X.p[i];
1389 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1393 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1394 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001396 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001397 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001398 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1399 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1400 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001401 Z.p[i - t - 1]--;
1402 }
1403 }
1404
1405 if( Q != NULL )
1406 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001407 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001408 Q->s = A->s * B->s;
1409 }
1410
1411 if( R != NULL )
1412 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001413 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001414 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001415 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001416
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001417 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001418 R->s = 1;
1419 }
1420
1421cleanup:
1422
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001423 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1424 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001425
1426 return( ret );
1427}
1428
1429/*
1430 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001431 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001432int 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 +00001433{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001434 mbedtls_mpi _B;
1435 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001436
1437 p[0] = ( b < 0 ) ? -b : b;
1438 _B.s = ( b < 0 ) ? -1 : 1;
1439 _B.n = 1;
1440 _B.p = p;
1441
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001442 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001443}
1444
1445/*
1446 * Modulo: R = A mod B
1447 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001448int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001449{
1450 int ret;
1451
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001452 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1453 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001455 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001457 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1458 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001460 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1461 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001462
1463cleanup:
1464
1465 return( ret );
1466}
1467
1468/*
1469 * Modulo: r = A mod b
1470 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001472{
Paul Bakker23986e52011-04-24 08:57:21 +00001473 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001474 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001475
1476 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001477 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001478
1479 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001480 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001481
1482 /*
1483 * handle trivial cases
1484 */
1485 if( b == 1 )
1486 {
1487 *r = 0;
1488 return( 0 );
1489 }
1490
1491 if( b == 2 )
1492 {
1493 *r = A->p[0] & 1;
1494 return( 0 );
1495 }
1496
1497 /*
1498 * general case
1499 */
Paul Bakker23986e52011-04-24 08:57:21 +00001500 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001501 {
Paul Bakker23986e52011-04-24 08:57:21 +00001502 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001503 y = ( y << biH ) | ( x >> biH );
1504 z = y / b;
1505 y -= z * b;
1506
1507 x <<= biH;
1508 y = ( y << biH ) | ( x >> biH );
1509 z = y / b;
1510 y -= z * b;
1511 }
1512
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001513 /*
1514 * If A is negative, then the current y represents a negative value.
1515 * Flipping it to the positive side.
1516 */
1517 if( A->s < 0 && y != 0 )
1518 y = b - y;
1519
Paul Bakker5121ce52009-01-03 21:22:43 +00001520 *r = y;
1521
1522 return( 0 );
1523}
1524
1525/*
1526 * Fast Montgomery initialization (thanks to Tom St Denis)
1527 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001528static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001529{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001530 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001531 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001532
1533 x = m0;
1534 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001535
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001536 for( i = biL; i >= 8; i /= 2 )
1537 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001538
1539 *mm = ~x + 1;
1540}
1541
1542/*
1543 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1544 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001545static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001546 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001547{
Paul Bakker23986e52011-04-24 08:57:21 +00001548 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001549 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001550
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001551 if( T->n < N->n + 1 || T->p == NULL )
1552 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1553
Paul Bakker5121ce52009-01-03 21:22:43 +00001554 memset( T->p, 0, T->n * ciL );
1555
1556 d = T->p;
1557 n = N->n;
1558 m = ( B->n < n ) ? B->n : n;
1559
1560 for( i = 0; i < n; i++ )
1561 {
1562 /*
1563 * T = (T + u0*B + u1*N) / 2^biL
1564 */
1565 u0 = A->p[i];
1566 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1567
1568 mpi_mul_hlp( m, B->p, d, u0 );
1569 mpi_mul_hlp( n, N->p, d, u1 );
1570
1571 *d++ = u0; d[n + 1] = 0;
1572 }
1573
Paul Bakker66d5d072014-06-17 16:39:18 +02001574 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001576 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001577 mpi_sub_hlp( n, N->p, A->p );
1578 else
1579 /* prevent timing attacks */
1580 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001581
1582 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001583}
1584
1585/*
1586 * Montgomery reduction: A = A * R^-1 mod N
1587 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001588static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001589{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001590 mbedtls_mpi_uint z = 1;
1591 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001592
Paul Bakker8ddb6452013-02-27 14:56:33 +01001593 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001594 U.p = &z;
1595
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001596 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001597}
1598
1599/*
1600 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1601 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001602int 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 +00001603{
Paul Bakker23986e52011-04-24 08:57:21 +00001604 int ret;
1605 size_t wbits, wsize, one = 1;
1606 size_t i, j, nblimbs;
1607 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001608 mbedtls_mpi_uint ei, mm, state;
1609 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001610 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001612 if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
1613 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001615 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1616 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001617
1618 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001619 * Init temps and window size
1620 */
1621 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001622 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1623 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001624 memset( W, 0, sizeof( W ) );
1625
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001626 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001627
1628 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1629 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1630
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001631 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1632 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001633
Paul Bakker5121ce52009-01-03 21:22:43 +00001634 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001635 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1636 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1637 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001638
1639 /*
Paul Bakker50546922012-05-19 08:40:49 +00001640 * Compensate for negative A (and correct at the end)
1641 */
1642 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001643 if( neg )
1644 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001645 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001646 Apos.s = 1;
1647 A = &Apos;
1648 }
1649
1650 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001651 * If 1st call, pre-compute R^2 mod N
1652 */
1653 if( _RR == NULL || _RR->p == NULL )
1654 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001655 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1656 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1657 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001658
1659 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001660 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001661 }
1662 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001663 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001664
1665 /*
1666 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1667 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001668 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1669 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001670 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001672
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001673 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001674
1675 /*
1676 * X = R^2 * R^-1 mod N = R mod N
1677 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001678 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001679 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001680
1681 if( wsize > 1 )
1682 {
1683 /*
1684 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1685 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001686 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001687
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1689 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001690
1691 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001692 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001693
Paul Bakker5121ce52009-01-03 21:22:43 +00001694 /*
1695 * W[i] = W[i - 1] * W[1]
1696 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001697 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001698 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001699 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1700 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001701
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001702 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001703 }
1704 }
1705
1706 nblimbs = E->n;
1707 bufsize = 0;
1708 nbits = 0;
1709 wbits = 0;
1710 state = 0;
1711
1712 while( 1 )
1713 {
1714 if( bufsize == 0 )
1715 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001716 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001717 break;
1718
Paul Bakker0d7702c2013-10-29 16:18:35 +01001719 nblimbs--;
1720
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001721 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001722 }
1723
1724 bufsize--;
1725
1726 ei = (E->p[nblimbs] >> bufsize) & 1;
1727
1728 /*
1729 * skip leading 0s
1730 */
1731 if( ei == 0 && state == 0 )
1732 continue;
1733
1734 if( ei == 0 && state == 1 )
1735 {
1736 /*
1737 * out of window, square X
1738 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001739 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001740 continue;
1741 }
1742
1743 /*
1744 * add ei to current window
1745 */
1746 state = 2;
1747
1748 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001749 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001750
1751 if( nbits == wsize )
1752 {
1753 /*
1754 * X = X^wsize R^-1 mod N
1755 */
1756 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001757 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001758
1759 /*
1760 * X = X * W[wbits] R^-1 mod N
1761 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001762 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001763
1764 state--;
1765 nbits = 0;
1766 wbits = 0;
1767 }
1768 }
1769
1770 /*
1771 * process the remaining bits
1772 */
1773 for( i = 0; i < nbits; i++ )
1774 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001775 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001776
1777 wbits <<= 1;
1778
Paul Bakker66d5d072014-06-17 16:39:18 +02001779 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001780 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001781 }
1782
1783 /*
1784 * X = A^E * R * R^-1 mod N = A^E mod N
1785 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001786 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001787
Paul Bakkerf6198c12012-05-16 08:02:29 +00001788 if( neg )
1789 {
1790 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001791 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001792 }
1793
Paul Bakker5121ce52009-01-03 21:22:43 +00001794cleanup:
1795
Paul Bakker66d5d072014-06-17 16:39:18 +02001796 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001797 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001798
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001799 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001800
Paul Bakker75a28602014-03-31 12:08:17 +02001801 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001802 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001803
1804 return( ret );
1805}
1806
Paul Bakker5121ce52009-01-03 21:22:43 +00001807/*
1808 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1809 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001810int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001811{
Paul Bakker23986e52011-04-24 08:57:21 +00001812 int ret;
1813 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001814 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001815
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001817
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001818 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1819 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001820
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001821 lz = mbedtls_mpi_lsb( &TA );
1822 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001823
Paul Bakker66d5d072014-06-17 16:39:18 +02001824 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001825 lz = lzt;
1826
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001827 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1828 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001829
Paul Bakker5121ce52009-01-03 21:22:43 +00001830 TA.s = TB.s = 1;
1831
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001832 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001833 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001834 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1835 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001836
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001837 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001838 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001839 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1840 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001841 }
1842 else
1843 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1845 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846 }
1847 }
1848
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001849 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1850 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001851
1852cleanup:
1853
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001854 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001855
1856 return( ret );
1857}
1858
Paul Bakker33dc46b2014-04-30 16:11:39 +02001859/*
1860 * Fill X with size bytes of random.
1861 *
1862 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001863 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001864 * deterministic, eg for tests).
1865 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001866int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001867 int (*f_rng)(void *, unsigned char *, size_t),
1868 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001869{
Paul Bakker23986e52011-04-24 08:57:21 +00001870 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001871 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001872
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001873 if( size > MBEDTLS_MPI_MAX_SIZE )
1874 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001875
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001876 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1877 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001878
1879cleanup:
1880 return( ret );
1881}
1882
Paul Bakker5121ce52009-01-03 21:22:43 +00001883/*
1884 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1885 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001886int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001887{
1888 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001889 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001890
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001891 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 )
1892 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001893
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1895 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1896 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001897
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001898 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001899
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001900 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001901 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001902 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001903 goto cleanup;
1904 }
1905
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001906 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1907 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1908 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1909 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001910
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001911 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1912 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1913 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1914 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001915
1916 do
1917 {
1918 while( ( TU.p[0] & 1 ) == 0 )
1919 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001920 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001921
1922 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1923 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001924 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1925 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001926 }
1927
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001928 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1929 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001930 }
1931
1932 while( ( TV.p[0] & 1 ) == 0 )
1933 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001934 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001935
1936 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1937 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001938 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1939 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001940 }
1941
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001942 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1943 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001944 }
1945
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001946 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001947 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001948 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1949 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1950 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001951 }
1952 else
1953 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001954 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1955 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1956 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001957 }
1958 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001960
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001961 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1962 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001963
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001964 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1965 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001966
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001967 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001968
1969cleanup:
1970
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001971 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1972 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1973 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001974
1975 return( ret );
1976}
1977
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001978#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001979
Paul Bakker5121ce52009-01-03 21:22:43 +00001980static const int small_prime[] =
1981{
1982 3, 5, 7, 11, 13, 17, 19, 23,
1983 29, 31, 37, 41, 43, 47, 53, 59,
1984 61, 67, 71, 73, 79, 83, 89, 97,
1985 101, 103, 107, 109, 113, 127, 131, 137,
1986 139, 149, 151, 157, 163, 167, 173, 179,
1987 181, 191, 193, 197, 199, 211, 223, 227,
1988 229, 233, 239, 241, 251, 257, 263, 269,
1989 271, 277, 281, 283, 293, 307, 311, 313,
1990 317, 331, 337, 347, 349, 353, 359, 367,
1991 373, 379, 383, 389, 397, 401, 409, 419,
1992 421, 431, 433, 439, 443, 449, 457, 461,
1993 463, 467, 479, 487, 491, 499, 503, 509,
1994 521, 523, 541, 547, 557, 563, 569, 571,
1995 577, 587, 593, 599, 601, 607, 613, 617,
1996 619, 631, 641, 643, 647, 653, 659, 661,
1997 673, 677, 683, 691, 701, 709, 719, 727,
1998 733, 739, 743, 751, 757, 761, 769, 773,
1999 787, 797, 809, 811, 821, 823, 827, 829,
2000 839, 853, 857, 859, 863, 877, 881, 883,
2001 887, 907, 911, 919, 929, 937, 941, 947,
2002 953, 967, 971, 977, 983, 991, 997, -103
2003};
2004
2005/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002006 * Small divisors test (X must be positive)
2007 *
2008 * Return values:
2009 * 0: no small factor (possible prime, more tests needed)
2010 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002011 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002012 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002013 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002014static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002015{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002016 int ret = 0;
2017 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002018 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002019
Paul Bakker5121ce52009-01-03 21:22:43 +00002020 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002021 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
2023 for( i = 0; small_prime[i] > 0; i++ )
2024 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002025 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002026 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002027
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002028 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002029
2030 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002031 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002032 }
2033
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002034cleanup:
2035 return( ret );
2036}
2037
2038/*
2039 * Miller-Rabin pseudo-primality test (HAC 4.24)
2040 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002041static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002042 int (*f_rng)(void *, unsigned char *, size_t),
2043 void *p_rng )
2044{
Pascal Junodb99183d2015-03-11 16:49:45 +01002045 int ret, count;
2046 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002047 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002048
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2050 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002051
Paul Bakker5121ce52009-01-03 21:22:43 +00002052 /*
2053 * W = |X| - 1
2054 * R = W >> lsb( W )
2055 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002056 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2057 s = mbedtls_mpi_lsb( &W );
2058 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2059 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002060
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002061 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002062 /*
2063 * HAC, table 4.4
2064 */
2065 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2066 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2067 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2068
2069 for( i = 0; i < n; i++ )
2070 {
2071 /*
2072 * pick a random A, 1 < A < |X| - 1
2073 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002074 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002075
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00002077 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002078 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002079 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00002080 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002081 A.p[0] |= 3;
2082
Pascal Junodb99183d2015-03-11 16:49:45 +01002083 count = 0;
2084 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002085 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002086
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002087 j = mbedtls_mpi_bitlen( &A );
2088 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002089 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002090 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002091 }
2092
2093 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002094 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002095 }
2096
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002097 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2098 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002099
2100 /*
2101 * A = A^R mod |X|
2102 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002103 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002104
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002105 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2106 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002107 continue;
2108
2109 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002110 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002111 {
2112 /*
2113 * A = A * A mod |X|
2114 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002115 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2116 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002117
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002118 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002119 break;
2120
2121 j++;
2122 }
2123
2124 /*
2125 * not prime if A != |X| - 1 or A == 1
2126 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002127 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2128 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002129 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002130 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002131 break;
2132 }
2133 }
2134
2135cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002136 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2137 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002138
2139 return( ret );
2140}
2141
2142/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002143 * Pseudo-primality test: small factors, then Miller-Rabin
2144 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002146 int (*f_rng)(void *, unsigned char *, size_t),
2147 void *p_rng )
2148{
2149 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002150 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002151
2152 XX.s = 1;
2153 XX.n = X->n;
2154 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002155
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002156 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2157 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2158 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002161 return( 0 );
2162
2163 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2164 {
2165 if( ret == 1 )
2166 return( 0 );
2167
2168 return( ret );
2169 }
2170
2171 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2172}
2173
2174/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002175 * Prime number generation
2176 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002178 int (*f_rng)(void *, unsigned char *, size_t),
2179 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002180{
Paul Bakker23986e52011-04-24 08:57:21 +00002181 int ret;
2182 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002183 mbedtls_mpi_uint r;
2184 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002185
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002186 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2187 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002189 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002190
2191 n = BITS_TO_LIMBS( nbits );
2192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002193 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002194
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002195 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002196 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002197
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002198 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002199
2200 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002201
2202 if( dh_flag == 0 )
2203 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002204 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002205 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002207 goto cleanup;
2208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002209 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002210 }
2211 }
2212 else
2213 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002214 /*
2215 * An necessary condition for Y and X = 2Y + 1 to be prime
2216 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2217 * Make sure it is satisfied, while keeping X = 3 mod 4
2218 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002219
2220 X->p[0] |= 2;
2221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002222 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002223 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002224 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002225 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002226 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002227
2228 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002229 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2230 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002231
2232 while( 1 )
2233 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002234 /*
2235 * First, check small factors for X and Y
2236 * before doing Miller-Rabin on any of them
2237 */
2238 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2239 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2240 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2241 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002242 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002243 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002244 }
2245
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002246 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002247 goto cleanup;
2248
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002249 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002250 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002251 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2252 * so up Y by 6 and X by 12.
2253 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002254 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2255 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002256 }
2257 }
2258
2259cleanup:
2260
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002261 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002262
2263 return( ret );
2264}
2265
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002266#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002268#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002269
Paul Bakker23986e52011-04-24 08:57:21 +00002270#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002271
2272static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2273{
2274 { 693, 609, 21 },
2275 { 1764, 868, 28 },
2276 { 768454923, 542167814, 1 }
2277};
2278
Paul Bakker5121ce52009-01-03 21:22:43 +00002279/*
2280 * Checkup routine
2281 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002282int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002283{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002284 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002285 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002287 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2288 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002289
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002290 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002291 "EFE021C2645FD1DC586E69184AF4A31E" \
2292 "D5F53E93B5F123FA41680867BA110131" \
2293 "944FE7952E2517337780CB0DB80E61AA" \
2294 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2295
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002296 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002297 "B2E7EFD37075B9F03FF989C7C5051C20" \
2298 "34D2A323810251127E7BF8625A4F49A5" \
2299 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2300 "5B5C25763222FEFCCFC38B832366C29E" ) );
2301
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002302 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002303 "0066A198186C18C10B2F5ED9B522752A" \
2304 "9830B69916E535C8F047518A889A43A5" \
2305 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002308
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002309 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002310 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2311 "9E857EA95A03512E2BAE7391688D264A" \
2312 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2313 "8001B72E848A38CAE1C65F78E56ABDEF" \
2314 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2315 "ECF677152EF804370C1A305CAF3B5BF1" \
2316 "30879B56C61DE584A0F53A2447A51E" ) );
2317
2318 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002319 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002321 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002322 {
2323 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002324 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002325
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002326 ret = 1;
2327 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002328 }
2329
2330 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002331 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002333 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002336 "256567336059E52CAE22925474705F39A94" ) );
2337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002339 "6613F26162223DF488E9CD48CC132C7A" \
2340 "0AC93C701B001B092E4E5B9F73BCD27B" \
2341 "9EE50D0657C77F374E903CDFA4C642" ) );
2342
2343 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002344 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002346 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2347 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002348 {
2349 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002350 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002351
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002352 ret = 1;
2353 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002354 }
2355
2356 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002357 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002358
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002361 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002362 "36E139AEA55215609D2816998ED020BB" \
2363 "BD96C37890F65171D948E9BC7CBAA4D9" \
2364 "325D24D6A3C12710F10A09FA08AB87" ) );
2365
2366 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002369 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002370 {
2371 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002372 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002373
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002374 ret = 1;
2375 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002376 }
2377
2378 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002379 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002381 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002384 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2385 "C3DBA76456363A10869622EAC2DD84EC" \
2386 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2387
2388 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002389 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002390
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002391 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002392 {
2393 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002394 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002395
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002396 ret = 1;
2397 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002398 }
2399
2400 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002401 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002402
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002403 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002404 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002405
Paul Bakker66d5d072014-06-17 16:39:18 +02002406 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002407 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002408 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2409 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002410
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002411 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002413 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002414 {
2415 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002416 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002417
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002418 ret = 1;
2419 goto cleanup;
2420 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002421 }
2422
2423 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002424 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002425
Paul Bakker5121ce52009-01-03 21:22:43 +00002426cleanup:
2427
2428 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002429 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002431 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2432 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002433
2434 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002435 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002436
2437 return( ret );
2438}
2439
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002441
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002442#endif /* MBEDTLS_BIGNUM_C */