blob: 79f25f08ec2935ada2dfa6be061bdc27d0977a2b [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 {
Simon Butcher29176892016-05-20 00:19:09 +0100123 if( ( p = (mbedtls_mpi_uint*)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
Simon Butcher29176892016-05-20 00:19:09 +0100161 if( ( p = (mbedtls_mpi_uint*)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;
Andres AGd1cc7f62017-01-06 13:17:35 +0000537 /*
538 * Round up the buffer length to an even value to ensure that there is
539 * enough room for hexadecimal values that can be represented in an odd
540 * number of digits.
541 */
542 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000543
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100544 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000545 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100546 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200547 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000548 }
549
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100550 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200551 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000552
553 if( X->s == -1 )
554 *p++ = '-';
555
556 if( radix == 16 )
557 {
Paul Bakker23986e52011-04-24 08:57:21 +0000558 int c;
559 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000560
Paul Bakker23986e52011-04-24 08:57:21 +0000561 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000562 {
Paul Bakker23986e52011-04-24 08:57:21 +0000563 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000564 {
Paul Bakker23986e52011-04-24 08:57:21 +0000565 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000566
Paul Bakker6c343d72014-07-10 14:36:19 +0200567 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000568 continue;
569
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000570 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000571 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000572 k = 1;
573 }
574 }
575 }
576 else
577 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000579
580 if( T.s == -1 )
581 T.s = 1;
582
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200583 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000584 }
585
586 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100587 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000588
589cleanup:
590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000592
593 return( ret );
594}
595
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200596#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000597/*
598 * Read X from an opened file
599 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200600int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000601{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000603 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000604 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000605 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000606 * Buffer should have space for (short) label and decimal formatted MPI,
607 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000608 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200609 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000610
611 memset( s, 0, sizeof( s ) );
612 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000614
615 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000616 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000618
Hanno Beckerb2034b72017-04-26 11:46:46 +0100619 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
620 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000621
622 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100623 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000624 if( mpi_get_digit( &d, radix, *p ) != 0 )
625 break;
626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200627 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000628}
629
630/*
631 * Write X into an opened file (or stdout if fout == NULL)
632 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200633int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000634{
Paul Bakker23986e52011-04-24 08:57:21 +0000635 int ret;
636 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000637 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000638 * Buffer should have space for (short) label and decimal formatted MPI,
639 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000640 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000642
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100643 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000644
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100645 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000646
647 if( p == NULL ) p = "";
648
649 plen = strlen( p );
650 slen = strlen( s );
651 s[slen++] = '\r';
652 s[slen++] = '\n';
653
654 if( fout != NULL )
655 {
656 if( fwrite( p, 1, plen, fout ) != plen ||
657 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000659 }
660 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000662
663cleanup:
664
665 return( ret );
666}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000668
669/*
670 * Import X from unsigned binary data, big endian
671 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000673{
Paul Bakker23986e52011-04-24 08:57:21 +0000674 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100675 size_t i, j;
676 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000677
Hanno Becker073c1992017-10-17 15:17:27 +0100678 /* Ensure that target MPI has exactly the necessary number of limbs */
679 if( X->n != limbs )
680 {
681 mbedtls_mpi_free( X );
682 mbedtls_mpi_init( X );
683 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
684 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000685
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200686 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000687
Hanno Becker073c1992017-10-17 15:17:27 +0100688 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000690
691cleanup:
692
693 return( ret );
694}
695
696/*
697 * Export X into unsigned binary data, big endian
698 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200699int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000700{
Paul Bakker23986e52011-04-24 08:57:21 +0000701 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000702
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000704
705 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
708 memset( buf, 0, buflen );
709
710 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
711 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
712
713 return( 0 );
714}
715
716/*
717 * Left-shift: X <<= count
718 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000720{
Paul Bakker23986e52011-04-24 08:57:21 +0000721 int ret;
722 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200723 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000724
725 v0 = count / (biL );
726 t1 = count & (biL - 1);
727
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200728 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000729
Paul Bakkerf9688572011-05-05 10:00:45 +0000730 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000732
733 ret = 0;
734
735 /*
736 * shift by count / limb_size
737 */
738 if( v0 > 0 )
739 {
Paul Bakker23986e52011-04-24 08:57:21 +0000740 for( i = X->n; i > v0; i-- )
741 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000742
Paul Bakker23986e52011-04-24 08:57:21 +0000743 for( ; i > 0; i-- )
744 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000745 }
746
747 /*
748 * shift by count % limb_size
749 */
750 if( t1 > 0 )
751 {
752 for( i = v0; i < X->n; i++ )
753 {
754 r1 = X->p[i] >> (biL - t1);
755 X->p[i] <<= t1;
756 X->p[i] |= r0;
757 r0 = r1;
758 }
759 }
760
761cleanup:
762
763 return( ret );
764}
765
766/*
767 * Right-shift: X >>= count
768 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200769int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000770{
Paul Bakker23986e52011-04-24 08:57:21 +0000771 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200772 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000773
774 v0 = count / biL;
775 v1 = count & (biL - 1);
776
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100777 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200778 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100779
Paul Bakker5121ce52009-01-03 21:22:43 +0000780 /*
781 * shift by count / limb_size
782 */
783 if( v0 > 0 )
784 {
785 for( i = 0; i < X->n - v0; i++ )
786 X->p[i] = X->p[i + v0];
787
788 for( ; i < X->n; i++ )
789 X->p[i] = 0;
790 }
791
792 /*
793 * shift by count % limb_size
794 */
795 if( v1 > 0 )
796 {
Paul Bakker23986e52011-04-24 08:57:21 +0000797 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000798 {
Paul Bakker23986e52011-04-24 08:57:21 +0000799 r1 = X->p[i - 1] << (biL - v1);
800 X->p[i - 1] >>= v1;
801 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000802 r0 = r1;
803 }
804 }
805
806 return( 0 );
807}
808
809/*
810 * Compare unsigned values
811 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200812int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000813{
Paul Bakker23986e52011-04-24 08:57:21 +0000814 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000815
Paul Bakker23986e52011-04-24 08:57:21 +0000816 for( i = X->n; i > 0; i-- )
817 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000818 break;
819
Paul Bakker23986e52011-04-24 08:57:21 +0000820 for( j = Y->n; j > 0; j-- )
821 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000822 break;
823
Paul Bakker23986e52011-04-24 08:57:21 +0000824 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000825 return( 0 );
826
827 if( i > j ) return( 1 );
828 if( j > i ) return( -1 );
829
Paul Bakker23986e52011-04-24 08:57:21 +0000830 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000831 {
Paul Bakker23986e52011-04-24 08:57:21 +0000832 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
833 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000834 }
835
836 return( 0 );
837}
838
839/*
840 * Compare signed values
841 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200842int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000843{
Paul Bakker23986e52011-04-24 08:57:21 +0000844 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000845
Paul Bakker23986e52011-04-24 08:57:21 +0000846 for( i = X->n; i > 0; i-- )
847 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000848 break;
849
Paul Bakker23986e52011-04-24 08:57:21 +0000850 for( j = Y->n; j > 0; j-- )
851 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000852 break;
853
Paul Bakker23986e52011-04-24 08:57:21 +0000854 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000855 return( 0 );
856
857 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000858 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000859
860 if( X->s > 0 && Y->s < 0 ) return( 1 );
861 if( Y->s > 0 && X->s < 0 ) return( -1 );
862
Paul Bakker23986e52011-04-24 08:57:21 +0000863 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000864 {
Paul Bakker23986e52011-04-24 08:57:21 +0000865 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
866 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000867 }
868
869 return( 0 );
870}
871
872/*
873 * Compare signed values
874 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200875int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000876{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200877 mbedtls_mpi Y;
878 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000879
880 *p = ( z < 0 ) ? -z : z;
881 Y.s = ( z < 0 ) ? -1 : 1;
882 Y.n = 1;
883 Y.p = p;
884
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200885 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000886}
887
888/*
889 * Unsigned addition: X = |A| + |B| (HAC 14.7)
890 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200891int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000892{
Paul Bakker23986e52011-04-24 08:57:21 +0000893 int ret;
894 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100895 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000896
897 if( X == B )
898 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200899 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000900 }
901
902 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200903 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200904
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000905 /*
906 * X should always be positive as a result of unsigned additions.
907 */
908 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000909
Paul Bakker23986e52011-04-24 08:57:21 +0000910 for( j = B->n; j > 0; j-- )
911 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000912 break;
913
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200914 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000915
916 o = B->p; p = X->p; c = 0;
917
Janos Follath6c922682015-10-30 17:43:11 +0100918 /*
919 * tmp is used because it might happen that p == o
920 */
Paul Bakker23986e52011-04-24 08:57:21 +0000921 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000922 {
Janos Follath6c922682015-10-30 17:43:11 +0100923 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000924 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100925 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000926 }
927
928 while( c != 0 )
929 {
930 if( i >= X->n )
931 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200932 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000933 p = X->p + i;
934 }
935
Paul Bakker2d319fd2012-09-16 21:34:26 +0000936 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000937 }
938
939cleanup:
940
941 return( ret );
942}
943
944/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200945 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000946 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000948{
Paul Bakker23986e52011-04-24 08:57:21 +0000949 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200950 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000951
952 for( i = c = 0; i < n; i++, s++, d++ )
953 {
954 z = ( *d < c ); *d -= c;
955 c = ( *d < *s ) + z; *d -= *s;
956 }
957
958 while( c != 0 )
959 {
960 z = ( *d < c ); *d -= c;
961 c = z; i++; d++;
962 }
963}
964
965/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100966 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000967 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200968int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000969{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200970 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000971 int ret;
972 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000973
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200974 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
975 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000976
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000978
979 if( X == B )
980 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200981 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000982 B = &TB;
983 }
984
985 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200986 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000987
Paul Bakker1ef7a532009-06-20 10:50:55 +0000988 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100989 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000990 */
991 X->s = 1;
992
Paul Bakker5121ce52009-01-03 21:22:43 +0000993 ret = 0;
994
Paul Bakker23986e52011-04-24 08:57:21 +0000995 for( n = B->n; n > 0; n-- )
996 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000997 break;
998
Paul Bakker23986e52011-04-24 08:57:21 +0000999 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001000
1001cleanup:
1002
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001003 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001004
1005 return( ret );
1006}
1007
1008/*
1009 * Signed addition: X = A + B
1010 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001011int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001012{
1013 int ret, s = A->s;
1014
1015 if( A->s * B->s < 0 )
1016 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001017 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001018 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001020 X->s = s;
1021 }
1022 else
1023 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001024 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001025 X->s = -s;
1026 }
1027 }
1028 else
1029 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001030 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001031 X->s = s;
1032 }
1033
1034cleanup:
1035
1036 return( ret );
1037}
1038
1039/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001040 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001041 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001043{
1044 int ret, s = A->s;
1045
1046 if( A->s * B->s > 0 )
1047 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001048 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001049 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001051 X->s = s;
1052 }
1053 else
1054 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001055 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001056 X->s = -s;
1057 }
1058 }
1059 else
1060 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001061 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001062 X->s = s;
1063 }
1064
1065cleanup:
1066
1067 return( ret );
1068}
1069
1070/*
1071 * Signed addition: X = A + b
1072 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001073int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001074{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001075 mbedtls_mpi _B;
1076 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001077
1078 p[0] = ( b < 0 ) ? -b : b;
1079 _B.s = ( b < 0 ) ? -1 : 1;
1080 _B.n = 1;
1081 _B.p = p;
1082
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001083 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001084}
1085
1086/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001087 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001088 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001089int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001090{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001091 mbedtls_mpi _B;
1092 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001093
1094 p[0] = ( b < 0 ) ? -b : b;
1095 _B.s = ( b < 0 ) ? -1 : 1;
1096 _B.n = 1;
1097 _B.p = p;
1098
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001099 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001100}
1101
1102/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001103 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001104 */
1105static
1106#if defined(__APPLE__) && defined(__arm__)
1107/*
1108 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1109 * appears to need this to prevent bad ARM code generation at -O3.
1110 */
1111__attribute__ ((noinline))
1112#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001113void 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 +00001114{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001116
1117#if defined(MULADDC_HUIT)
1118 for( ; i >= 8; i -= 8 )
1119 {
1120 MULADDC_INIT
1121 MULADDC_HUIT
1122 MULADDC_STOP
1123 }
1124
1125 for( ; i > 0; i-- )
1126 {
1127 MULADDC_INIT
1128 MULADDC_CORE
1129 MULADDC_STOP
1130 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001131#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001132 for( ; i >= 16; i -= 16 )
1133 {
1134 MULADDC_INIT
1135 MULADDC_CORE MULADDC_CORE
1136 MULADDC_CORE MULADDC_CORE
1137 MULADDC_CORE MULADDC_CORE
1138 MULADDC_CORE MULADDC_CORE
1139
1140 MULADDC_CORE MULADDC_CORE
1141 MULADDC_CORE MULADDC_CORE
1142 MULADDC_CORE MULADDC_CORE
1143 MULADDC_CORE MULADDC_CORE
1144 MULADDC_STOP
1145 }
1146
1147 for( ; i >= 8; i -= 8 )
1148 {
1149 MULADDC_INIT
1150 MULADDC_CORE MULADDC_CORE
1151 MULADDC_CORE MULADDC_CORE
1152
1153 MULADDC_CORE MULADDC_CORE
1154 MULADDC_CORE MULADDC_CORE
1155 MULADDC_STOP
1156 }
1157
1158 for( ; i > 0; i-- )
1159 {
1160 MULADDC_INIT
1161 MULADDC_CORE
1162 MULADDC_STOP
1163 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001164#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001165
1166 t++;
1167
1168 do {
1169 *d += c; c = ( *d < c ); d++;
1170 }
1171 while( c != 0 );
1172}
1173
1174/*
1175 * Baseline multiplication: X = A * B (HAC 14.12)
1176 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001177int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001178{
Paul Bakker23986e52011-04-24 08:57:21 +00001179 int ret;
1180 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001181 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001182
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001183 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001185 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1186 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001187
Paul Bakker23986e52011-04-24 08:57:21 +00001188 for( i = A->n; i > 0; i-- )
1189 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001190 break;
1191
Paul Bakker23986e52011-04-24 08:57:21 +00001192 for( j = B->n; j > 0; j-- )
1193 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001194 break;
1195
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001196 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1197 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001198
Paul Bakker23986e52011-04-24 08:57:21 +00001199 for( i++; j > 0; j-- )
1200 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001201
1202 X->s = A->s * B->s;
1203
1204cleanup:
1205
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001206 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001207
1208 return( ret );
1209}
1210
1211/*
1212 * Baseline multiplication: X = A * b
1213 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001214int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001215{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001216 mbedtls_mpi _B;
1217 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001218
1219 _B.s = 1;
1220 _B.n = 1;
1221 _B.p = p;
1222 p[0] = b;
1223
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001224 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001225}
1226
1227/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001228 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1229 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001230 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001231static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1232 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001233{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001234#if defined(MBEDTLS_HAVE_UDBL)
1235 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001236#else
Simon Butcher9803d072016-01-03 00:24:34 +00001237 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1238 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001239 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1240 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001241 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001242#endif
1243
Simon Butcher15b15d12015-11-26 19:35:03 +00001244 /*
1245 * Check for overflow
1246 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001247 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001248 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001249 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001250
Simon Butcherf5ba0452015-12-27 23:01:55 +00001251 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001252 }
1253
1254#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001255 dividend = (mbedtls_t_udbl) u1 << biL;
1256 dividend |= (mbedtls_t_udbl) u0;
1257 quotient = dividend / d;
1258 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1259 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1260
1261 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001262 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001263
1264 return (mbedtls_mpi_uint) quotient;
1265#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001266
1267 /*
1268 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1269 * Vol. 2 - Seminumerical Algorithms, Knuth
1270 */
1271
1272 /*
1273 * Normalize the divisor, d, and dividend, u0, u1
1274 */
1275 s = mbedtls_clz( d );
1276 d = d << s;
1277
1278 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001279 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001280 u0 = u0 << s;
1281
1282 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001283 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001284
1285 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001286 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001287
1288 /*
1289 * Find the first quotient and remainder
1290 */
1291 q1 = u1 / d1;
1292 r0 = u1 - d1 * q1;
1293
1294 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1295 {
1296 q1 -= 1;
1297 r0 += d1;
1298
1299 if ( r0 >= radix ) break;
1300 }
1301
Simon Butcherf5ba0452015-12-27 23:01:55 +00001302 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001303 q0 = rAX / d1;
1304 r0 = rAX - q0 * d1;
1305
1306 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1307 {
1308 q0 -= 1;
1309 r0 += d1;
1310
1311 if ( r0 >= radix ) break;
1312 }
1313
1314 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001315 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001316
1317 quotient = q1 * radix + q0;
1318
1319 return quotient;
1320#endif
1321}
1322
1323/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001324 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001325 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001326int 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 +00001327{
Paul Bakker23986e52011-04-24 08:57:21 +00001328 int ret;
1329 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001330 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1333 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001335 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1336 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001338 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001339 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001340 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1341 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001342 return( 0 );
1343 }
1344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001345 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1346 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001347 X.s = Y.s = 1;
1348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001349 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1350 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1351 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1352 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001353
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001354 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001355 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001356 {
1357 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001358 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1359 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001360 }
1361 else k = 0;
1362
1363 n = X.n - 1;
1364 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001366
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001367 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001368 {
1369 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001370 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001371 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001373
1374 for( i = n; i > t ; i-- )
1375 {
1376 if( X.p[i] >= Y.p[t] )
1377 Z.p[i - t - 1] = ~0;
1378 else
1379 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001380 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1381 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001382 }
1383
1384 Z.p[i - t - 1]++;
1385 do
1386 {
1387 Z.p[i - t - 1]--;
1388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001389 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001390 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001391 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001393
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001394 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001395 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1396 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001397 T2.p[2] = X.p[i];
1398 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001400
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001401 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1402 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1403 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001404
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001405 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001406 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001407 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1408 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1409 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001410 Z.p[i - t - 1]--;
1411 }
1412 }
1413
1414 if( Q != NULL )
1415 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001416 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001417 Q->s = A->s * B->s;
1418 }
1419
1420 if( R != NULL )
1421 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001422 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001423 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001424 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001425
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001426 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001427 R->s = 1;
1428 }
1429
1430cleanup:
1431
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001432 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1433 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001434
1435 return( ret );
1436}
1437
1438/*
1439 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001440 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001441int 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 +00001442{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001443 mbedtls_mpi _B;
1444 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001445
1446 p[0] = ( b < 0 ) ? -b : b;
1447 _B.s = ( b < 0 ) ? -1 : 1;
1448 _B.n = 1;
1449 _B.p = p;
1450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001451 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001452}
1453
1454/*
1455 * Modulo: R = A mod B
1456 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001457int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001458{
1459 int ret;
1460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001461 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1462 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001463
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001464 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1467 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001468
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001469 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1470 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001471
1472cleanup:
1473
1474 return( ret );
1475}
1476
1477/*
1478 * Modulo: r = A mod b
1479 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001480int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001481{
Paul Bakker23986e52011-04-24 08:57:21 +00001482 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001483 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001484
1485 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001486 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001487
1488 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001489 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001490
1491 /*
1492 * handle trivial cases
1493 */
1494 if( b == 1 )
1495 {
1496 *r = 0;
1497 return( 0 );
1498 }
1499
1500 if( b == 2 )
1501 {
1502 *r = A->p[0] & 1;
1503 return( 0 );
1504 }
1505
1506 /*
1507 * general case
1508 */
Paul Bakker23986e52011-04-24 08:57:21 +00001509 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001510 {
Paul Bakker23986e52011-04-24 08:57:21 +00001511 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001512 y = ( y << biH ) | ( x >> biH );
1513 z = y / b;
1514 y -= z * b;
1515
1516 x <<= biH;
1517 y = ( y << biH ) | ( x >> biH );
1518 z = y / b;
1519 y -= z * b;
1520 }
1521
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001522 /*
1523 * If A is negative, then the current y represents a negative value.
1524 * Flipping it to the positive side.
1525 */
1526 if( A->s < 0 && y != 0 )
1527 y = b - y;
1528
Paul Bakker5121ce52009-01-03 21:22:43 +00001529 *r = y;
1530
1531 return( 0 );
1532}
1533
1534/*
1535 * Fast Montgomery initialization (thanks to Tom St Denis)
1536 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001537static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001538{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001540 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001541
1542 x = m0;
1543 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001544
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001545 for( i = biL; i >= 8; i /= 2 )
1546 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001547
1548 *mm = ~x + 1;
1549}
1550
1551/*
1552 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1553 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001554static 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 +02001555 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001556{
Paul Bakker23986e52011-04-24 08:57:21 +00001557 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001558 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001559
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001560 if( T->n < N->n + 1 || T->p == NULL )
1561 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1562
Paul Bakker5121ce52009-01-03 21:22:43 +00001563 memset( T->p, 0, T->n * ciL );
1564
1565 d = T->p;
1566 n = N->n;
1567 m = ( B->n < n ) ? B->n : n;
1568
1569 for( i = 0; i < n; i++ )
1570 {
1571 /*
1572 * T = (T + u0*B + u1*N) / 2^biL
1573 */
1574 u0 = A->p[i];
1575 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1576
1577 mpi_mul_hlp( m, B->p, d, u0 );
1578 mpi_mul_hlp( n, N->p, d, u1 );
1579
1580 *d++ = u0; d[n + 1] = 0;
1581 }
1582
Paul Bakker66d5d072014-06-17 16:39:18 +02001583 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001584
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001585 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001586 mpi_sub_hlp( n, N->p, A->p );
1587 else
1588 /* prevent timing attacks */
1589 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001590
1591 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001592}
1593
1594/*
1595 * Montgomery reduction: A = A * R^-1 mod N
1596 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001597static 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 +00001598{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001599 mbedtls_mpi_uint z = 1;
1600 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001601
Paul Bakker8ddb6452013-02-27 14:56:33 +01001602 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001603 U.p = &z;
1604
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001605 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001606}
1607
1608/*
1609 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1610 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001611int 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 +00001612{
Paul Bakker23986e52011-04-24 08:57:21 +00001613 int ret;
1614 size_t wbits, wsize, one = 1;
1615 size_t i, j, nblimbs;
1616 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001617 mbedtls_mpi_uint ei, mm, state;
1618 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001619 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001620
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001621 if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
1622 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001623
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001624 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1625 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001626
1627 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001628 * Init temps and window size
1629 */
1630 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001631 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1632 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001633 memset( W, 0, sizeof( W ) );
1634
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001635 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001636
1637 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1638 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1639
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001640 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1641 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001642
Paul Bakker5121ce52009-01-03 21:22:43 +00001643 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001644 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1645 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1646 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001647
1648 /*
Paul Bakker50546922012-05-19 08:40:49 +00001649 * Compensate for negative A (and correct at the end)
1650 */
1651 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001652 if( neg )
1653 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001654 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001655 Apos.s = 1;
1656 A = &Apos;
1657 }
1658
1659 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001660 * If 1st call, pre-compute R^2 mod N
1661 */
1662 if( _RR == NULL || _RR->p == NULL )
1663 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001664 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1665 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1666 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001667
1668 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001669 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001670 }
1671 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001672 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001673
1674 /*
1675 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1676 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001677 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1678 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001679 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001680 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001681
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001682 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001683
1684 /*
1685 * X = R^2 * R^-1 mod N = R mod N
1686 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001687 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001688 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001689
1690 if( wsize > 1 )
1691 {
1692 /*
1693 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1694 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001695 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001697 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1698 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001699
1700 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001701 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001702
Paul Bakker5121ce52009-01-03 21:22:43 +00001703 /*
1704 * W[i] = W[i - 1] * W[1]
1705 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001706 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001707 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001708 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1709 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001710
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001711 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001712 }
1713 }
1714
1715 nblimbs = E->n;
1716 bufsize = 0;
1717 nbits = 0;
1718 wbits = 0;
1719 state = 0;
1720
1721 while( 1 )
1722 {
1723 if( bufsize == 0 )
1724 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001725 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001726 break;
1727
Paul Bakker0d7702c2013-10-29 16:18:35 +01001728 nblimbs--;
1729
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001730 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001731 }
1732
1733 bufsize--;
1734
1735 ei = (E->p[nblimbs] >> bufsize) & 1;
1736
1737 /*
1738 * skip leading 0s
1739 */
1740 if( ei == 0 && state == 0 )
1741 continue;
1742
1743 if( ei == 0 && state == 1 )
1744 {
1745 /*
1746 * out of window, square X
1747 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001748 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001749 continue;
1750 }
1751
1752 /*
1753 * add ei to current window
1754 */
1755 state = 2;
1756
1757 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001758 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001759
1760 if( nbits == wsize )
1761 {
1762 /*
1763 * X = X^wsize R^-1 mod N
1764 */
1765 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001766 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001767
1768 /*
1769 * X = X * W[wbits] R^-1 mod N
1770 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001771 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001772
1773 state--;
1774 nbits = 0;
1775 wbits = 0;
1776 }
1777 }
1778
1779 /*
1780 * process the remaining bits
1781 */
1782 for( i = 0; i < nbits; i++ )
1783 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001784 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001785
1786 wbits <<= 1;
1787
Paul Bakker66d5d072014-06-17 16:39:18 +02001788 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001789 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001790 }
1791
1792 /*
1793 * X = A^E * R * R^-1 mod N = A^E mod N
1794 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001795 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001796
Hanno Beckera4af1c42017-04-18 09:07:45 +01001797 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001798 {
1799 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001800 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001801 }
1802
Paul Bakker5121ce52009-01-03 21:22:43 +00001803cleanup:
1804
Paul Bakker66d5d072014-06-17 16:39:18 +02001805 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001806 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001807
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001808 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001809
Paul Bakker75a28602014-03-31 12:08:17 +02001810 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001811 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001812
1813 return( ret );
1814}
1815
Paul Bakker5121ce52009-01-03 21:22:43 +00001816/*
1817 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1818 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001819int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001820{
Paul Bakker23986e52011-04-24 08:57:21 +00001821 int ret;
1822 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001823 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001824
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001825 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001826
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001827 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1828 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001829
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830 lz = mbedtls_mpi_lsb( &TA );
1831 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001832
Paul Bakker66d5d072014-06-17 16:39:18 +02001833 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001834 lz = lzt;
1835
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001836 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1837 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001838
Paul Bakker5121ce52009-01-03 21:22:43 +00001839 TA.s = TB.s = 1;
1840
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001841 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001842 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001843 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1844 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001845
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001846 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001847 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001848 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1849 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001850 }
1851 else
1852 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001853 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1854 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001855 }
1856 }
1857
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001858 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1859 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001860
1861cleanup:
1862
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001863 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001864
1865 return( ret );
1866}
1867
Paul Bakker33dc46b2014-04-30 16:11:39 +02001868/*
1869 * Fill X with size bytes of random.
1870 *
1871 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001872 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001873 * deterministic, eg for tests).
1874 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001875int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001876 int (*f_rng)(void *, unsigned char *, size_t),
1877 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001878{
Paul Bakker23986e52011-04-24 08:57:21 +00001879 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001881
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882 if( size > MBEDTLS_MPI_MAX_SIZE )
1883 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001884
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001885 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1886 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001887
1888cleanup:
1889 return( ret );
1890}
1891
Paul Bakker5121ce52009-01-03 21:22:43 +00001892/*
1893 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1894 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001895int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001896{
1897 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001898 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001899
Hanno Becker4bcb4912017-04-18 15:49:39 +01001900 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001901 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001902
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001903 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1904 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1905 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001906
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001907 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001908
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001909 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001910 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001911 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001912 goto cleanup;
1913 }
1914
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001915 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1916 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1917 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1918 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001919
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001920 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1921 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1922 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1923 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001924
1925 do
1926 {
1927 while( ( TU.p[0] & 1 ) == 0 )
1928 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001930
1931 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1932 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001933 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1934 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001935 }
1936
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001937 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1938 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001939 }
1940
1941 while( ( TV.p[0] & 1 ) == 0 )
1942 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001943 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001944
1945 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1946 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001947 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1948 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001949 }
1950
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001951 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1952 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001953 }
1954
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001955 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001956 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001957 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1958 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1959 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001960 }
1961 else
1962 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1964 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1965 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001966 }
1967 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001968 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001970 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1971 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001972
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001973 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1974 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001975
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001976 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001977
1978cleanup:
1979
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001980 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1981 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1982 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001983
1984 return( ret );
1985}
1986
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001987#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001988
Paul Bakker5121ce52009-01-03 21:22:43 +00001989static const int small_prime[] =
1990{
1991 3, 5, 7, 11, 13, 17, 19, 23,
1992 29, 31, 37, 41, 43, 47, 53, 59,
1993 61, 67, 71, 73, 79, 83, 89, 97,
1994 101, 103, 107, 109, 113, 127, 131, 137,
1995 139, 149, 151, 157, 163, 167, 173, 179,
1996 181, 191, 193, 197, 199, 211, 223, 227,
1997 229, 233, 239, 241, 251, 257, 263, 269,
1998 271, 277, 281, 283, 293, 307, 311, 313,
1999 317, 331, 337, 347, 349, 353, 359, 367,
2000 373, 379, 383, 389, 397, 401, 409, 419,
2001 421, 431, 433, 439, 443, 449, 457, 461,
2002 463, 467, 479, 487, 491, 499, 503, 509,
2003 521, 523, 541, 547, 557, 563, 569, 571,
2004 577, 587, 593, 599, 601, 607, 613, 617,
2005 619, 631, 641, 643, 647, 653, 659, 661,
2006 673, 677, 683, 691, 701, 709, 719, 727,
2007 733, 739, 743, 751, 757, 761, 769, 773,
2008 787, 797, 809, 811, 821, 823, 827, 829,
2009 839, 853, 857, 859, 863, 877, 881, 883,
2010 887, 907, 911, 919, 929, 937, 941, 947,
2011 953, 967, 971, 977, 983, 991, 997, -103
2012};
2013
2014/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002015 * Small divisors test (X must be positive)
2016 *
2017 * Return values:
2018 * 0: no small factor (possible prime, more tests needed)
2019 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002020 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002021 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002022 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002024{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002025 int ret = 0;
2026 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002027 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002028
Paul Bakker5121ce52009-01-03 21:22:43 +00002029 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002030 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002031
2032 for( i = 0; small_prime[i] > 0; i++ )
2033 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002035 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002036
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002037 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002038
2039 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002040 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002041 }
2042
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002043cleanup:
2044 return( ret );
2045}
2046
2047/*
2048 * Miller-Rabin pseudo-primality test (HAC 4.24)
2049 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002050static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002051 int (*f_rng)(void *, unsigned char *, size_t),
2052 void *p_rng )
2053{
Pascal Junodb99183d2015-03-11 16:49:45 +01002054 int ret, count;
2055 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002056 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002057
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2059 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002060
Paul Bakker5121ce52009-01-03 21:22:43 +00002061 /*
2062 * W = |X| - 1
2063 * R = W >> lsb( W )
2064 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002065 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2066 s = mbedtls_mpi_lsb( &W );
2067 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2068 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002069
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002070 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002071 /*
2072 * HAC, table 4.4
2073 */
2074 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2075 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2076 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2077
2078 for( i = 0; i < n; i++ )
2079 {
2080 /*
2081 * pick a random A, 1 < A < |X| - 1
2082 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002083 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002084
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002085 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00002086 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002087 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002088 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00002089 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002090 A.p[0] |= 3;
2091
Pascal Junodb99183d2015-03-11 16:49:45 +01002092 count = 0;
2093 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002094 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002095
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002096 j = mbedtls_mpi_bitlen( &A );
2097 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002098 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002099 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002100 }
2101
2102 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002103 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002104 }
2105
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002106 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2107 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002108
2109 /*
2110 * A = A^R mod |X|
2111 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002112 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002113
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002114 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2115 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002116 continue;
2117
2118 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002119 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002120 {
2121 /*
2122 * A = A * A mod |X|
2123 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002124 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2125 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002127 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002128 break;
2129
2130 j++;
2131 }
2132
2133 /*
2134 * not prime if A != |X| - 1 or A == 1
2135 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002136 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2137 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002138 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002139 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002140 break;
2141 }
2142 }
2143
2144cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2146 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002147
2148 return( ret );
2149}
2150
2151/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002152 * Pseudo-primality test: small factors, then Miller-Rabin
2153 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002154int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002155 int (*f_rng)(void *, unsigned char *, size_t),
2156 void *p_rng )
2157{
2158 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002159 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002160
2161 XX.s = 1;
2162 XX.n = X->n;
2163 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002164
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002165 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2166 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2167 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002168
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002169 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002170 return( 0 );
2171
2172 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2173 {
2174 if( ret == 1 )
2175 return( 0 );
2176
2177 return( ret );
2178 }
2179
2180 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2181}
2182
2183/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002184 * Prime number generation
2185 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002186int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002187 int (*f_rng)(void *, unsigned char *, size_t),
2188 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002189{
Paul Bakker23986e52011-04-24 08:57:21 +00002190 int ret;
2191 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002192 mbedtls_mpi_uint r;
2193 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002194
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002195 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2196 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002197
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002199
2200 n = BITS_TO_LIMBS( nbits );
2201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002202 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002203
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002204 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002205 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002206
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002207 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002208
2209 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002210
2211 if( dh_flag == 0 )
2212 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002213 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002214 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002215 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002216 goto cleanup;
2217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002218 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002219 }
2220 }
2221 else
2222 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002223 /*
2224 * An necessary condition for Y and X = 2Y + 1 to be prime
2225 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2226 * Make sure it is satisfied, while keeping X = 3 mod 4
2227 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002228
2229 X->p[0] |= 2;
2230
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002231 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002232 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002233 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002234 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002235 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002236
2237 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002238 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2239 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002240
2241 while( 1 )
2242 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002243 /*
2244 * First, check small factors for X and Y
2245 * before doing Miller-Rabin on any of them
2246 */
2247 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2248 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2249 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2250 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002251 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002252 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002253 }
2254
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002255 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002256 goto cleanup;
2257
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002258 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002259 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002260 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2261 * so up Y by 6 and X by 12.
2262 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002263 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2264 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002265 }
2266 }
2267
2268cleanup:
2269
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002270 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002271
2272 return( ret );
2273}
2274
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002275#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002276
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002277#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002278
Paul Bakker23986e52011-04-24 08:57:21 +00002279#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002280
2281static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2282{
2283 { 693, 609, 21 },
2284 { 1764, 868, 28 },
2285 { 768454923, 542167814, 1 }
2286};
2287
Paul Bakker5121ce52009-01-03 21:22:43 +00002288/*
2289 * Checkup routine
2290 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002291int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002292{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002293 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002294 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002295
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002296 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2297 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002300 "EFE021C2645FD1DC586E69184AF4A31E" \
2301 "D5F53E93B5F123FA41680867BA110131" \
2302 "944FE7952E2517337780CB0DB80E61AA" \
2303 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2304
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002305 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002306 "B2E7EFD37075B9F03FF989C7C5051C20" \
2307 "34D2A323810251127E7BF8625A4F49A5" \
2308 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2309 "5B5C25763222FEFCCFC38B832366C29E" ) );
2310
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002311 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002312 "0066A198186C18C10B2F5ED9B522752A" \
2313 "9830B69916E535C8F047518A889A43A5" \
2314 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2315
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002316 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002317
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002318 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002319 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2320 "9E857EA95A03512E2BAE7391688D264A" \
2321 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2322 "8001B72E848A38CAE1C65F78E56ABDEF" \
2323 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2324 "ECF677152EF804370C1A305CAF3B5BF1" \
2325 "30879B56C61DE584A0F53A2447A51E" ) );
2326
2327 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002328 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002329
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002331 {
2332 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002333 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002334
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002335 ret = 1;
2336 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002337 }
2338
2339 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002340 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002344 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002345 "256567336059E52CAE22925474705F39A94" ) );
2346
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002348 "6613F26162223DF488E9CD48CC132C7A" \
2349 "0AC93C701B001B092E4E5B9F73BCD27B" \
2350 "9EE50D0657C77F374E903CDFA4C642" ) );
2351
2352 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002354
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002355 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2356 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002357 {
2358 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002361 ret = 1;
2362 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002363 }
2364
2365 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002366 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002367
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002368 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002370 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002371 "36E139AEA55215609D2816998ED020BB" \
2372 "BD96C37890F65171D948E9BC7CBAA4D9" \
2373 "325D24D6A3C12710F10A09FA08AB87" ) );
2374
2375 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002378 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002379 {
2380 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002381 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002382
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002383 ret = 1;
2384 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002385 }
2386
2387 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002388 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002390 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002392 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002393 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2394 "C3DBA76456363A10869622EAC2DD84EC" \
2395 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2396
2397 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002398 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002400 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002401 {
2402 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002403 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002404
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002405 ret = 1;
2406 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002407 }
2408
2409 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002410 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002411
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002412 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002413 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002414
Paul Bakker66d5d072014-06-17 16:39:18 +02002415 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002416 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002417 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2418 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002419
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002420 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002421
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002422 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002423 {
2424 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002425 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002426
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002427 ret = 1;
2428 goto cleanup;
2429 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002430 }
2431
2432 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002433 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002434
Paul Bakker5121ce52009-01-03 21:22:43 +00002435cleanup:
2436
2437 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002438 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002439
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2441 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002442
2443 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002444 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002445
2446 return( ret );
2447}
2448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002449#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002451#endif /* MBEDTLS_BIGNUM_C */