blob: d6f415c6f9e59a69170c9054164141fcb5b34f7a [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000048
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <string.h>
50
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000052#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020053#else
Rich Evans00ab4702015-02-06 13:43:58 +000054#include <stdio.h>
55#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020057#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020059#endif
60
Paul Bakker34617722014-06-13 17:20:13 +020061/* Implementation that should never be optimized out by the compiler */
Alexey Skalozube17a8da2016-01-13 17:19:33 +020062static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) {
Alexey Skalozub3d53f412016-01-13 16:53:40 +020063 volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0;
Paul Bakker34617722014-06-13 17:20:13 +020064}
65
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020066#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000067#define biL (ciL << 3) /* bits in limb */
68#define biH (ciL << 2) /* half limb size */
69
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010070#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
71
Paul Bakker5121ce52009-01-03 21:22:43 +000072/*
73 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020074 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000075 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020076#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
77#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000078
79/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000080 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000081 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000083{
Paul Bakker6c591fa2011-05-05 11:49:20 +000084 if( X == NULL )
85 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000086
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 X->s = 1;
88 X->n = 0;
89 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000090}
91
92/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000094 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020095void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000096{
Paul Bakker6c591fa2011-05-05 11:49:20 +000097 if( X == NULL )
98 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000099
Paul Bakker6c591fa2011-05-05 11:49:20 +0000100 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000101 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200102 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200103 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000104 }
105
Paul Bakker6c591fa2011-05-05 11:49:20 +0000106 X->s = 1;
107 X->n = 0;
108 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000109}
110
111/*
112 * Enlarge to the specified number of limbs
113 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200114int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000115{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000117
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200118 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200119 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000120
Paul Bakker5121ce52009-01-03 21:22:43 +0000121 if( X->n < nblimbs )
122 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200123 if( ( p = mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200124 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000125
Paul Bakker5121ce52009-01-03 21:22:43 +0000126 if( X->p != NULL )
127 {
128 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200129 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000131 }
132
133 X->n = nblimbs;
134 X->p = p;
135 }
136
137 return( 0 );
138}
139
140/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100141 * Resize down as much as possible,
142 * while keeping at least the specified number of limbs
143 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100145{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100147 size_t i;
148
149 /* Actually resize up in this case */
150 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152
153 for( i = X->n - 1; i > 0; i-- )
154 if( X->p[i] != 0 )
155 break;
156 i++;
157
158 if( i < nblimbs )
159 i = nblimbs;
160
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200161 if( ( p = mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200162 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100164 if( X->p != NULL )
165 {
166 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200167 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100169 }
170
171 X->n = i;
172 X->p = p;
173
174 return( 0 );
175}
176
177/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000178 * Copy the contents of Y into X
179 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000181{
Paul Bakker23986e52011-04-24 08:57:21 +0000182 int ret;
183 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000184
185 if( X == Y )
186 return( 0 );
187
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200188 if( Y->p == NULL )
189 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200191 return( 0 );
192 }
193
Paul Bakker5121ce52009-01-03 21:22:43 +0000194 for( i = Y->n - 1; i > 0; i-- )
195 if( Y->p[i] != 0 )
196 break;
197 i++;
198
199 X->s = Y->s;
200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200201 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000202
203 memset( X->p, 0, X->n * ciL );
204 memcpy( X->p, Y->p, i * ciL );
205
206cleanup:
207
208 return( ret );
209}
210
211/*
212 * Swap the contents of X and Y
213 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200214void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000215{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218 memcpy( &T, X, sizeof( mbedtls_mpi ) );
219 memcpy( X, Y, sizeof( mbedtls_mpi ) );
220 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000221}
222
223/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100224 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100225 * about whether the assignment was made or not.
226 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100227 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100229{
230 int ret = 0;
231 size_t i;
232
Pascal Junodb99183d2015-03-11 16:49:45 +0100233 /* make sure assign is 0 or 1 in a time-constant manner */
234 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100235
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100237
Paul Bakker66d5d072014-06-17 16:39:18 +0200238 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100239
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100240 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200241 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100242
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100243 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200244 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100245
246cleanup:
247 return( ret );
248}
249
250/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100251 * Conditionally swap X and Y, without leaking information
252 * about whether the swap was made or not.
253 * Here it is not ok to simply swap the pointers, which whould lead to
254 * different memory access patterns when X and Y are used afterwards.
255 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100257{
258 int ret, s;
259 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100261
262 if( X == Y )
263 return( 0 );
264
Pascal Junodb99183d2015-03-11 16:49:45 +0100265 /* make sure swap is 0 or 1 in a time-constant manner */
266 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
269 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100270
271 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200272 X->s = X->s * ( 1 - swap ) + Y->s * swap;
273 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274
275
276 for( i = 0; i < X->n; i++ )
277 {
278 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200279 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
280 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100281 }
282
283cleanup:
284 return( ret );
285}
286
287/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000288 * Set value from integer
289 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200290int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000291{
292 int ret;
293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000295 memset( X->p, 0, X->n * ciL );
296
297 X->p[0] = ( z < 0 ) ? -z : z;
298 X->s = ( z < 0 ) ? -1 : 1;
299
300cleanup:
301
302 return( ret );
303}
304
305/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000306 * Get a specific bit
307 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000309{
310 if( X->n * biL <= pos )
311 return( 0 );
312
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200313 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000314}
315
316/*
317 * Set a bit to a specific value of 0 or 1
318 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200319int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000320{
321 int ret = 0;
322 size_t off = pos / biL;
323 size_t idx = pos % biL;
324
325 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200327
Paul Bakker2f5947e2011-05-18 15:47:11 +0000328 if( X->n * biL <= pos )
329 {
330 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200331 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200333 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000334 }
335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
337 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338
339cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200340
Paul Bakker2f5947e2011-05-18 15:47:11 +0000341 return( ret );
342}
343
344/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200345 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000346 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000348{
Paul Bakker23986e52011-04-24 08:57:21 +0000349 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000350
351 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000352 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000353 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
354 return( count );
355
356 return( 0 );
357}
358
359/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000360 * Count leading zero bits in a given integer
361 */
362static size_t mbedtls_clz( const mbedtls_mpi_uint x )
363{
364 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100365 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000366
367 for( j = 0; j < biL; j++ )
368 {
369 if( x & mask ) break;
370
371 mask >>= 1;
372 }
373
374 return j;
375}
376
377/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200378 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200380size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000381{
Paul Bakker23986e52011-04-24 08:57:21 +0000382 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000383
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200384 if( X->n == 0 )
385 return( 0 );
386
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 for( i = X->n - 1; i > 0; i-- )
388 if( X->p[i] != 0 )
389 break;
390
Simon Butcher15b15d12015-11-26 19:35:03 +0000391 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000392
Paul Bakker23986e52011-04-24 08:57:21 +0000393 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000394}
395
396/*
397 * Return the total size in bytes
398 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000400{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200401 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000402}
403
404/*
405 * Convert an ASCII character to digit value
406 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000408{
409 *d = 255;
410
411 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
412 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
413 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
414
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415 if( *d >= (mbedtls_mpi_uint) radix )
416 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
418 return( 0 );
419}
420
421/*
422 * Import from an ASCII string
423 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000425{
Paul Bakker23986e52011-04-24 08:57:21 +0000426 int ret;
427 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 mbedtls_mpi_uint d;
429 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000430
431 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000435
Paul Bakkerff60ee62010-03-16 21:09:09 +0000436 slen = strlen( s );
437
Paul Bakker5121ce52009-01-03 21:22:43 +0000438 if( radix == 16 )
439 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100440 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200441 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
442
Paul Bakkerff60ee62010-03-16 21:09:09 +0000443 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
446 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000447
Paul Bakker23986e52011-04-24 08:57:21 +0000448 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000449 {
Paul Bakker23986e52011-04-24 08:57:21 +0000450 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000451 {
452 X->s = -1;
453 break;
454 }
455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200457 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 }
459 }
460 else
461 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000463
Paul Bakkerff60ee62010-03-16 21:09:09 +0000464 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000465 {
466 if( i == 0 && s[i] == '-' )
467 {
468 X->s = -1;
469 continue;
470 }
471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
473 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000474
475 if( X->s == 1 )
476 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000478 }
479 else
480 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000482 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000483 }
484 }
485
486cleanup:
487
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200488 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000489
490 return( ret );
491}
492
493/*
494 * Helper to write the digits high-order first
495 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000497{
498 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000500
501 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
505 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
508 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000509
510 if( r < 10 )
511 *(*p)++ = (char)( r + 0x30 );
512 else
513 *(*p)++ = (char)( r + 0x37 );
514
515cleanup:
516
517 return( ret );
518}
519
520/*
521 * Export into an ASCII string
522 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100523int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
524 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000525{
Paul Bakker23986e52011-04-24 08:57:21 +0000526 int ret = 0;
527 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000528 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000530
531 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000533
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200534 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000535 if( radix >= 4 ) n >>= 1;
536 if( radix >= 16 ) n >>= 1;
537 n += 3;
538
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100539 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000540 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100541 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000543 }
544
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100545 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000547
548 if( X->s == -1 )
549 *p++ = '-';
550
551 if( radix == 16 )
552 {
Paul Bakker23986e52011-04-24 08:57:21 +0000553 int c;
554 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000555
Paul Bakker23986e52011-04-24 08:57:21 +0000556 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000557 {
Paul Bakker23986e52011-04-24 08:57:21 +0000558 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000559 {
Paul Bakker23986e52011-04-24 08:57:21 +0000560 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000561
Paul Bakker6c343d72014-07-10 14:36:19 +0200562 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000563 continue;
564
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000565 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000566 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000567 k = 1;
568 }
569 }
570 }
571 else
572 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000574
575 if( T.s == -1 )
576 T.s = 1;
577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000579 }
580
581 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100582 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000583
584cleanup:
585
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000587
588 return( ret );
589}
590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000592/*
593 * Read X from an opened file
594 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200595int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000596{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000598 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000599 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000600 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000601 * Buffer should have space for (short) label and decimal formatted MPI,
602 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000603 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000605
606 memset( s, 0, sizeof( s ) );
607 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000609
610 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000611 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000613
Paul Bakker5121ce52009-01-03 21:22:43 +0000614 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
615 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
616
617 p = s + slen;
618 while( --p >= s )
619 if( mpi_get_digit( &d, radix, *p ) != 0 )
620 break;
621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000623}
624
625/*
626 * Write X into an opened file (or stdout if fout == NULL)
627 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000629{
Paul Bakker23986e52011-04-24 08:57:21 +0000630 int ret;
631 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000632 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000633 * Buffer should have space for (short) label and decimal formatted MPI,
634 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000635 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200636 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000637
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100638 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000639
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100640 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000641
642 if( p == NULL ) p = "";
643
644 plen = strlen( p );
645 slen = strlen( s );
646 s[slen++] = '\r';
647 s[slen++] = '\n';
648
649 if( fout != NULL )
650 {
651 if( fwrite( p, 1, plen, fout ) != plen ||
652 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000654 }
655 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000657
658cleanup:
659
660 return( ret );
661}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000663
664/*
665 * Import X from unsigned binary data, big endian
666 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000668{
Paul Bakker23986e52011-04-24 08:57:21 +0000669 int ret;
670 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000671
672 for( n = 0; n < buflen; n++ )
673 if( buf[n] != 0 )
674 break;
675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
677 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000678
Paul Bakker23986e52011-04-24 08:57:21 +0000679 for( i = buflen, j = 0; i > n; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000681
682cleanup:
683
684 return( ret );
685}
686
687/*
688 * Export X into unsigned binary data, big endian
689 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000691{
Paul Bakker23986e52011-04-24 08:57:21 +0000692 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000693
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200694 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000695
696 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
699 memset( buf, 0, buflen );
700
701 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
702 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
703
704 return( 0 );
705}
706
707/*
708 * Left-shift: X <<= count
709 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000711{
Paul Bakker23986e52011-04-24 08:57:21 +0000712 int ret;
713 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000715
716 v0 = count / (biL );
717 t1 = count & (biL - 1);
718
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200719 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000720
Paul Bakkerf9688572011-05-05 10:00:45 +0000721 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000723
724 ret = 0;
725
726 /*
727 * shift by count / limb_size
728 */
729 if( v0 > 0 )
730 {
Paul Bakker23986e52011-04-24 08:57:21 +0000731 for( i = X->n; i > v0; i-- )
732 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000733
Paul Bakker23986e52011-04-24 08:57:21 +0000734 for( ; i > 0; i-- )
735 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000736 }
737
738 /*
739 * shift by count % limb_size
740 */
741 if( t1 > 0 )
742 {
743 for( i = v0; i < X->n; i++ )
744 {
745 r1 = X->p[i] >> (biL - t1);
746 X->p[i] <<= t1;
747 X->p[i] |= r0;
748 r0 = r1;
749 }
750 }
751
752cleanup:
753
754 return( ret );
755}
756
757/*
758 * Right-shift: X >>= count
759 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200760int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000761{
Paul Bakker23986e52011-04-24 08:57:21 +0000762 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200763 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000764
765 v0 = count / biL;
766 v1 = count & (biL - 1);
767
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100768 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200769 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100770
Paul Bakker5121ce52009-01-03 21:22:43 +0000771 /*
772 * shift by count / limb_size
773 */
774 if( v0 > 0 )
775 {
776 for( i = 0; i < X->n - v0; i++ )
777 X->p[i] = X->p[i + v0];
778
779 for( ; i < X->n; i++ )
780 X->p[i] = 0;
781 }
782
783 /*
784 * shift by count % limb_size
785 */
786 if( v1 > 0 )
787 {
Paul Bakker23986e52011-04-24 08:57:21 +0000788 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000789 {
Paul Bakker23986e52011-04-24 08:57:21 +0000790 r1 = X->p[i - 1] << (biL - v1);
791 X->p[i - 1] >>= v1;
792 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000793 r0 = r1;
794 }
795 }
796
797 return( 0 );
798}
799
800/*
801 * Compare unsigned values
802 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200803int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000804{
Paul Bakker23986e52011-04-24 08:57:21 +0000805 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000806
Paul Bakker23986e52011-04-24 08:57:21 +0000807 for( i = X->n; i > 0; i-- )
808 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000809 break;
810
Paul Bakker23986e52011-04-24 08:57:21 +0000811 for( j = Y->n; j > 0; j-- )
812 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000813 break;
814
Paul Bakker23986e52011-04-24 08:57:21 +0000815 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000816 return( 0 );
817
818 if( i > j ) return( 1 );
819 if( j > i ) return( -1 );
820
Paul Bakker23986e52011-04-24 08:57:21 +0000821 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000822 {
Paul Bakker23986e52011-04-24 08:57:21 +0000823 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
824 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000825 }
826
827 return( 0 );
828}
829
830/*
831 * Compare signed values
832 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200833int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000834{
Paul Bakker23986e52011-04-24 08:57:21 +0000835 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000836
Paul Bakker23986e52011-04-24 08:57:21 +0000837 for( i = X->n; i > 0; i-- )
838 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000839 break;
840
Paul Bakker23986e52011-04-24 08:57:21 +0000841 for( j = Y->n; j > 0; j-- )
842 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000843 break;
844
Paul Bakker23986e52011-04-24 08:57:21 +0000845 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000846 return( 0 );
847
848 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000849 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000850
851 if( X->s > 0 && Y->s < 0 ) return( 1 );
852 if( Y->s > 0 && X->s < 0 ) return( -1 );
853
Paul Bakker23986e52011-04-24 08:57:21 +0000854 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000855 {
Paul Bakker23986e52011-04-24 08:57:21 +0000856 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
857 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000858 }
859
860 return( 0 );
861}
862
863/*
864 * Compare signed values
865 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200866int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000867{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200868 mbedtls_mpi Y;
869 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000870
871 *p = ( z < 0 ) ? -z : z;
872 Y.s = ( z < 0 ) ? -1 : 1;
873 Y.n = 1;
874 Y.p = p;
875
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200876 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000877}
878
879/*
880 * Unsigned addition: X = |A| + |B| (HAC 14.7)
881 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200882int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000883{
Paul Bakker23986e52011-04-24 08:57:21 +0000884 int ret;
885 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100886 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000887
888 if( X == B )
889 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200890 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000891 }
892
893 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200894 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200895
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000896 /*
897 * X should always be positive as a result of unsigned additions.
898 */
899 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000900
Paul Bakker23986e52011-04-24 08:57:21 +0000901 for( j = B->n; j > 0; j-- )
902 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000903 break;
904
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200905 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000906
907 o = B->p; p = X->p; c = 0;
908
Janos Follath6c922682015-10-30 17:43:11 +0100909 /*
910 * tmp is used because it might happen that p == o
911 */
Paul Bakker23986e52011-04-24 08:57:21 +0000912 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000913 {
Janos Follath6c922682015-10-30 17:43:11 +0100914 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000915 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100916 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000917 }
918
919 while( c != 0 )
920 {
921 if( i >= X->n )
922 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200923 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000924 p = X->p + i;
925 }
926
Paul Bakker2d319fd2012-09-16 21:34:26 +0000927 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000928 }
929
930cleanup:
931
932 return( ret );
933}
934
935/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200936 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000937 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200938static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000939{
Paul Bakker23986e52011-04-24 08:57:21 +0000940 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000942
943 for( i = c = 0; i < n; i++, s++, d++ )
944 {
945 z = ( *d < c ); *d -= c;
946 c = ( *d < *s ) + z; *d -= *s;
947 }
948
949 while( c != 0 )
950 {
951 z = ( *d < c ); *d -= c;
952 c = z; i++; d++;
953 }
954}
955
956/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100957 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000958 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200959int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000960{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200961 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000962 int ret;
963 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000964
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200965 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
966 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000967
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200968 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000969
970 if( X == B )
971 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200972 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000973 B = &TB;
974 }
975
976 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000978
Paul Bakker1ef7a532009-06-20 10:50:55 +0000979 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100980 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000981 */
982 X->s = 1;
983
Paul Bakker5121ce52009-01-03 21:22:43 +0000984 ret = 0;
985
Paul Bakker23986e52011-04-24 08:57:21 +0000986 for( n = B->n; n > 0; n-- )
987 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000988 break;
989
Paul Bakker23986e52011-04-24 08:57:21 +0000990 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000991
992cleanup:
993
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200994 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000995
996 return( ret );
997}
998
999/*
1000 * Signed addition: X = A + B
1001 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001002int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001003{
1004 int ret, s = A->s;
1005
1006 if( A->s * B->s < 0 )
1007 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001008 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001009 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001010 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001011 X->s = s;
1012 }
1013 else
1014 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001015 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001016 X->s = -s;
1017 }
1018 }
1019 else
1020 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001021 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001022 X->s = s;
1023 }
1024
1025cleanup:
1026
1027 return( ret );
1028}
1029
1030/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001031 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001032 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001033int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001034{
1035 int ret, s = A->s;
1036
1037 if( A->s * B->s > 0 )
1038 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001039 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001040 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001041 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001042 X->s = s;
1043 }
1044 else
1045 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001046 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001047 X->s = -s;
1048 }
1049 }
1050 else
1051 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001052 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001053 X->s = s;
1054 }
1055
1056cleanup:
1057
1058 return( ret );
1059}
1060
1061/*
1062 * Signed addition: X = A + b
1063 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001064int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001065{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001066 mbedtls_mpi _B;
1067 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001068
1069 p[0] = ( b < 0 ) ? -b : b;
1070 _B.s = ( b < 0 ) ? -1 : 1;
1071 _B.n = 1;
1072 _B.p = p;
1073
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001074 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001075}
1076
1077/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001078 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001079 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001080int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001081{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001082 mbedtls_mpi _B;
1083 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001084
1085 p[0] = ( b < 0 ) ? -b : b;
1086 _B.s = ( b < 0 ) ? -1 : 1;
1087 _B.n = 1;
1088 _B.p = p;
1089
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001090 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001091}
1092
1093/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001094 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001095 */
1096static
1097#if defined(__APPLE__) && defined(__arm__)
1098/*
1099 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1100 * appears to need this to prevent bad ARM code generation at -O3.
1101 */
1102__attribute__ ((noinline))
1103#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001104void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001105{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001106 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001107
1108#if defined(MULADDC_HUIT)
1109 for( ; i >= 8; i -= 8 )
1110 {
1111 MULADDC_INIT
1112 MULADDC_HUIT
1113 MULADDC_STOP
1114 }
1115
1116 for( ; i > 0; i-- )
1117 {
1118 MULADDC_INIT
1119 MULADDC_CORE
1120 MULADDC_STOP
1121 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001122#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001123 for( ; i >= 16; i -= 16 )
1124 {
1125 MULADDC_INIT
1126 MULADDC_CORE MULADDC_CORE
1127 MULADDC_CORE MULADDC_CORE
1128 MULADDC_CORE MULADDC_CORE
1129 MULADDC_CORE MULADDC_CORE
1130
1131 MULADDC_CORE MULADDC_CORE
1132 MULADDC_CORE MULADDC_CORE
1133 MULADDC_CORE MULADDC_CORE
1134 MULADDC_CORE MULADDC_CORE
1135 MULADDC_STOP
1136 }
1137
1138 for( ; i >= 8; i -= 8 )
1139 {
1140 MULADDC_INIT
1141 MULADDC_CORE MULADDC_CORE
1142 MULADDC_CORE MULADDC_CORE
1143
1144 MULADDC_CORE MULADDC_CORE
1145 MULADDC_CORE MULADDC_CORE
1146 MULADDC_STOP
1147 }
1148
1149 for( ; i > 0; i-- )
1150 {
1151 MULADDC_INIT
1152 MULADDC_CORE
1153 MULADDC_STOP
1154 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001155#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001156
1157 t++;
1158
1159 do {
1160 *d += c; c = ( *d < c ); d++;
1161 }
1162 while( c != 0 );
1163}
1164
1165/*
1166 * Baseline multiplication: X = A * B (HAC 14.12)
1167 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001168int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001169{
Paul Bakker23986e52011-04-24 08:57:21 +00001170 int ret;
1171 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001172 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001173
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001174 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001175
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001176 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1177 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001178
Paul Bakker23986e52011-04-24 08:57:21 +00001179 for( i = A->n; i > 0; i-- )
1180 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001181 break;
1182
Paul Bakker23986e52011-04-24 08:57:21 +00001183 for( j = B->n; j > 0; j-- )
1184 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001185 break;
1186
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001187 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1188 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001189
Paul Bakker23986e52011-04-24 08:57:21 +00001190 for( i++; j > 0; j-- )
1191 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001192
1193 X->s = A->s * B->s;
1194
1195cleanup:
1196
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001197 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001198
1199 return( ret );
1200}
1201
1202/*
1203 * Baseline multiplication: X = A * b
1204 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001205int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001206{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001207 mbedtls_mpi _B;
1208 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001209
1210 _B.s = 1;
1211 _B.n = 1;
1212 _B.p = p;
1213 p[0] = b;
1214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001215 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001216}
1217
1218/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001219 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1220 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001221 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001222static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1223 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001224{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001225#if defined(MBEDTLS_HAVE_UDBL)
1226 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001227#else
Simon Butcher9803d072016-01-03 00:24:34 +00001228 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1229 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001230 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1231 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001232 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001233#endif
1234
Simon Butcher15b15d12015-11-26 19:35:03 +00001235 /*
1236 * Check for overflow
1237 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001238 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001239 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001240 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001241
Simon Butcherf5ba0452015-12-27 23:01:55 +00001242 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001243 }
1244
1245#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001246 dividend = (mbedtls_t_udbl) u1 << biL;
1247 dividend |= (mbedtls_t_udbl) u0;
1248 quotient = dividend / d;
1249 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1250 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1251
1252 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001253 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001254
1255 return (mbedtls_mpi_uint) quotient;
1256#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001257
1258 /*
1259 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1260 * Vol. 2 - Seminumerical Algorithms, Knuth
1261 */
1262
1263 /*
1264 * Normalize the divisor, d, and dividend, u0, u1
1265 */
1266 s = mbedtls_clz( d );
1267 d = d << s;
1268
1269 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001270 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001271 u0 = u0 << s;
1272
1273 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001274 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001275
1276 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001277 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001278
1279 /*
1280 * Find the first quotient and remainder
1281 */
1282 q1 = u1 / d1;
1283 r0 = u1 - d1 * q1;
1284
1285 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1286 {
1287 q1 -= 1;
1288 r0 += d1;
1289
1290 if ( r0 >= radix ) break;
1291 }
1292
Simon Butcherf5ba0452015-12-27 23:01:55 +00001293 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001294 q0 = rAX / d1;
1295 r0 = rAX - q0 * d1;
1296
1297 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1298 {
1299 q0 -= 1;
1300 r0 += d1;
1301
1302 if ( r0 >= radix ) break;
1303 }
1304
1305 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001306 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001307
1308 quotient = q1 * radix + q0;
1309
1310 return quotient;
1311#endif
1312}
1313
1314/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001315 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001316 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001317int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001318{
Paul Bakker23986e52011-04-24 08:57:21 +00001319 int ret;
1320 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001321 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001322
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001323 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1324 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001326 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1327 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001329 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001330 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001331 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1332 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001333 return( 0 );
1334 }
1335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1337 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001338 X.s = Y.s = 1;
1339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001340 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1341 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1342 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1343 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001344
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001345 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001346 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001347 {
1348 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001349 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1350 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001351 }
1352 else k = 0;
1353
1354 n = X.n - 1;
1355 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001356 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001358 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001359 {
1360 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001361 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001362 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001363 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001364
1365 for( i = n; i > t ; i-- )
1366 {
1367 if( X.p[i] >= Y.p[t] )
1368 Z.p[i - t - 1] = ~0;
1369 else
1370 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001371 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1372 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001373 }
1374
1375 Z.p[i - t - 1]++;
1376 do
1377 {
1378 Z.p[i - t - 1]--;
1379
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001380 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001381 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001382 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001383 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001385 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001386 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1387 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001388 T2.p[2] = X.p[i];
1389 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1393 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1394 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001396 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001397 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001398 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1399 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1400 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001401 Z.p[i - t - 1]--;
1402 }
1403 }
1404
1405 if( Q != NULL )
1406 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001407 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001408 Q->s = A->s * B->s;
1409 }
1410
1411 if( R != NULL )
1412 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001413 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001414 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001415 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001416
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001417 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001418 R->s = 1;
1419 }
1420
1421cleanup:
1422
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001423 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1424 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001425
1426 return( ret );
1427}
1428
1429/*
1430 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001431 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001432int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001433{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001434 mbedtls_mpi _B;
1435 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001436
1437 p[0] = ( b < 0 ) ? -b : b;
1438 _B.s = ( b < 0 ) ? -1 : 1;
1439 _B.n = 1;
1440 _B.p = p;
1441
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001442 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001443}
1444
1445/*
1446 * Modulo: R = A mod B
1447 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001448int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001449{
1450 int ret;
1451
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001452 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1453 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001455 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001457 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1458 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001460 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1461 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001462
1463cleanup:
1464
1465 return( ret );
1466}
1467
1468/*
1469 * Modulo: r = A mod b
1470 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001472{
Paul Bakker23986e52011-04-24 08:57:21 +00001473 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001474 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001475
1476 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001477 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001478
1479 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001480 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001481
1482 /*
1483 * handle trivial cases
1484 */
1485 if( b == 1 )
1486 {
1487 *r = 0;
1488 return( 0 );
1489 }
1490
1491 if( b == 2 )
1492 {
1493 *r = A->p[0] & 1;
1494 return( 0 );
1495 }
1496
1497 /*
1498 * general case
1499 */
Paul Bakker23986e52011-04-24 08:57:21 +00001500 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001501 {
Paul Bakker23986e52011-04-24 08:57:21 +00001502 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001503 y = ( y << biH ) | ( x >> biH );
1504 z = y / b;
1505 y -= z * b;
1506
1507 x <<= biH;
1508 y = ( y << biH ) | ( x >> biH );
1509 z = y / b;
1510 y -= z * b;
1511 }
1512
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001513 /*
1514 * If A is negative, then the current y represents a negative value.
1515 * Flipping it to the positive side.
1516 */
1517 if( A->s < 0 && y != 0 )
1518 y = b - y;
1519
Paul Bakker5121ce52009-01-03 21:22:43 +00001520 *r = y;
1521
1522 return( 0 );
1523}
1524
1525/*
1526 * Fast Montgomery initialization (thanks to Tom St Denis)
1527 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001528static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001529{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001530 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001531 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001532
1533 x = m0;
1534 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001535
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001536 for( i = biL; i >= 8; i /= 2 )
1537 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001538
1539 *mm = ~x + 1;
1540}
1541
1542/*
1543 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1544 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001545static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1546 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001547{
Paul Bakker23986e52011-04-24 08:57:21 +00001548 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001549 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001550
1551 memset( T->p, 0, T->n * ciL );
1552
1553 d = T->p;
1554 n = N->n;
1555 m = ( B->n < n ) ? B->n : n;
1556
1557 for( i = 0; i < n; i++ )
1558 {
1559 /*
1560 * T = (T + u0*B + u1*N) / 2^biL
1561 */
1562 u0 = A->p[i];
1563 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1564
1565 mpi_mul_hlp( m, B->p, d, u0 );
1566 mpi_mul_hlp( n, N->p, d, u1 );
1567
1568 *d++ = u0; d[n + 1] = 0;
1569 }
1570
Paul Bakker66d5d072014-06-17 16:39:18 +02001571 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001572
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001573 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001574 mpi_sub_hlp( n, N->p, A->p );
1575 else
1576 /* prevent timing attacks */
1577 mpi_sub_hlp( n, A->p, T->p );
1578}
1579
1580/*
1581 * Montgomery reduction: A = A * R^-1 mod N
1582 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001583static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001584{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001585 mbedtls_mpi_uint z = 1;
1586 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001587
Paul Bakker8ddb6452013-02-27 14:56:33 +01001588 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001589 U.p = &z;
1590
1591 mpi_montmul( A, &U, N, mm, T );
1592}
1593
1594/*
1595 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1596 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001597int 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 +00001598{
Paul Bakker23986e52011-04-24 08:57:21 +00001599 int ret;
1600 size_t wbits, wsize, one = 1;
1601 size_t i, j, nblimbs;
1602 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001603 mbedtls_mpi_uint ei, mm, state;
1604 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001605 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001606
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001607 if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
1608 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001609
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001610 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1611 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001612
1613 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001614 * Init temps and window size
1615 */
1616 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001617 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1618 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001619 memset( W, 0, sizeof( W ) );
1620
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001621 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001622
1623 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1624 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1625
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001626 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1627 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001628
Paul Bakker5121ce52009-01-03 21:22:43 +00001629 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001630 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1631 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1632 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001633
1634 /*
Paul Bakker50546922012-05-19 08:40:49 +00001635 * Compensate for negative A (and correct at the end)
1636 */
1637 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001638 if( neg )
1639 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001640 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001641 Apos.s = 1;
1642 A = &Apos;
1643 }
1644
1645 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001646 * If 1st call, pre-compute R^2 mod N
1647 */
1648 if( _RR == NULL || _RR->p == NULL )
1649 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001650 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1651 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1652 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001653
1654 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001655 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001656 }
1657 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001658 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001659
1660 /*
1661 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1662 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001663 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1664 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001665 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001666 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001667
1668 mpi_montmul( &W[1], &RR, N, mm, &T );
1669
1670 /*
1671 * X = R^2 * R^-1 mod N = R mod N
1672 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001673 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001674 mpi_montred( X, N, mm, &T );
1675
1676 if( wsize > 1 )
1677 {
1678 /*
1679 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1680 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001681 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001682
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001683 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1684 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001685
1686 for( i = 0; i < wsize - 1; i++ )
1687 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001688
Paul Bakker5121ce52009-01-03 21:22:43 +00001689 /*
1690 * W[i] = W[i - 1] * W[1]
1691 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001692 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001693 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001694 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1695 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001696
1697 mpi_montmul( &W[i], &W[1], N, mm, &T );
1698 }
1699 }
1700
1701 nblimbs = E->n;
1702 bufsize = 0;
1703 nbits = 0;
1704 wbits = 0;
1705 state = 0;
1706
1707 while( 1 )
1708 {
1709 if( bufsize == 0 )
1710 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001711 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001712 break;
1713
Paul Bakker0d7702c2013-10-29 16:18:35 +01001714 nblimbs--;
1715
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001716 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001717 }
1718
1719 bufsize--;
1720
1721 ei = (E->p[nblimbs] >> bufsize) & 1;
1722
1723 /*
1724 * skip leading 0s
1725 */
1726 if( ei == 0 && state == 0 )
1727 continue;
1728
1729 if( ei == 0 && state == 1 )
1730 {
1731 /*
1732 * out of window, square X
1733 */
1734 mpi_montmul( X, X, N, mm, &T );
1735 continue;
1736 }
1737
1738 /*
1739 * add ei to current window
1740 */
1741 state = 2;
1742
1743 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001744 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001745
1746 if( nbits == wsize )
1747 {
1748 /*
1749 * X = X^wsize R^-1 mod N
1750 */
1751 for( i = 0; i < wsize; i++ )
1752 mpi_montmul( X, X, N, mm, &T );
1753
1754 /*
1755 * X = X * W[wbits] R^-1 mod N
1756 */
1757 mpi_montmul( X, &W[wbits], N, mm, &T );
1758
1759 state--;
1760 nbits = 0;
1761 wbits = 0;
1762 }
1763 }
1764
1765 /*
1766 * process the remaining bits
1767 */
1768 for( i = 0; i < nbits; i++ )
1769 {
1770 mpi_montmul( X, X, N, mm, &T );
1771
1772 wbits <<= 1;
1773
Paul Bakker66d5d072014-06-17 16:39:18 +02001774 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001775 mpi_montmul( X, &W[1], N, mm, &T );
1776 }
1777
1778 /*
1779 * X = A^E * R * R^-1 mod N = A^E mod N
1780 */
1781 mpi_montred( X, N, mm, &T );
1782
Paul Bakkerf6198c12012-05-16 08:02:29 +00001783 if( neg )
1784 {
1785 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001786 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001787 }
1788
Paul Bakker5121ce52009-01-03 21:22:43 +00001789cleanup:
1790
Paul Bakker66d5d072014-06-17 16:39:18 +02001791 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001792 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001793
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001794 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001795
Paul Bakker75a28602014-03-31 12:08:17 +02001796 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001797 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001798
1799 return( ret );
1800}
1801
Paul Bakker5121ce52009-01-03 21:22:43 +00001802/*
1803 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1804 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001805int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001806{
Paul Bakker23986e52011-04-24 08:57:21 +00001807 int ret;
1808 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001809 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001810
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001811 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001812
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001813 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1814 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001815
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816 lz = mbedtls_mpi_lsb( &TA );
1817 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001818
Paul Bakker66d5d072014-06-17 16:39:18 +02001819 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001820 lz = lzt;
1821
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001822 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1823 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001824
Paul Bakker5121ce52009-01-03 21:22:43 +00001825 TA.s = TB.s = 1;
1826
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001827 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001828 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001829 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1830 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001831
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001832 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001833 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001834 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1835 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001836 }
1837 else
1838 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001839 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1840 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001841 }
1842 }
1843
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1845 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846
1847cleanup:
1848
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001849 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001850
1851 return( ret );
1852}
1853
Paul Bakker33dc46b2014-04-30 16:11:39 +02001854/*
1855 * Fill X with size bytes of random.
1856 *
1857 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001858 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001859 * deterministic, eg for tests).
1860 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001861int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001862 int (*f_rng)(void *, unsigned char *, size_t),
1863 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001864{
Paul Bakker23986e52011-04-24 08:57:21 +00001865 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001866 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001867
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001868 if( size > MBEDTLS_MPI_MAX_SIZE )
1869 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001870
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001871 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1872 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001873
1874cleanup:
1875 return( ret );
1876}
1877
Paul Bakker5121ce52009-01-03 21:22:43 +00001878/*
1879 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1880 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001881int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001882{
1883 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001884 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001885
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001886 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 )
1887 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001888
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001889 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1890 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1891 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001892
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001893 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001894
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001895 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001896 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001897 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001898 goto cleanup;
1899 }
1900
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001901 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1902 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1903 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1904 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001905
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001906 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1907 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1908 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1909 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001910
1911 do
1912 {
1913 while( ( TU.p[0] & 1 ) == 0 )
1914 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001915 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001916
1917 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1918 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001919 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1920 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001921 }
1922
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001923 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1924 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001925 }
1926
1927 while( ( TV.p[0] & 1 ) == 0 )
1928 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001930
1931 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1932 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001933 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1934 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &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( &V1, 1 ) );
1938 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001939 }
1940
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001941 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001942 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001943 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1944 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1945 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001946 }
1947 else
1948 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001949 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1950 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1951 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001952 }
1953 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001954 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001955
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001956 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1957 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001958
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1960 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001961
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001962 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001963
1964cleanup:
1965
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001966 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1967 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1968 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
1970 return( ret );
1971}
1972
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001973#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001974
Paul Bakker5121ce52009-01-03 21:22:43 +00001975static const int small_prime[] =
1976{
1977 3, 5, 7, 11, 13, 17, 19, 23,
1978 29, 31, 37, 41, 43, 47, 53, 59,
1979 61, 67, 71, 73, 79, 83, 89, 97,
1980 101, 103, 107, 109, 113, 127, 131, 137,
1981 139, 149, 151, 157, 163, 167, 173, 179,
1982 181, 191, 193, 197, 199, 211, 223, 227,
1983 229, 233, 239, 241, 251, 257, 263, 269,
1984 271, 277, 281, 283, 293, 307, 311, 313,
1985 317, 331, 337, 347, 349, 353, 359, 367,
1986 373, 379, 383, 389, 397, 401, 409, 419,
1987 421, 431, 433, 439, 443, 449, 457, 461,
1988 463, 467, 479, 487, 491, 499, 503, 509,
1989 521, 523, 541, 547, 557, 563, 569, 571,
1990 577, 587, 593, 599, 601, 607, 613, 617,
1991 619, 631, 641, 643, 647, 653, 659, 661,
1992 673, 677, 683, 691, 701, 709, 719, 727,
1993 733, 739, 743, 751, 757, 761, 769, 773,
1994 787, 797, 809, 811, 821, 823, 827, 829,
1995 839, 853, 857, 859, 863, 877, 881, 883,
1996 887, 907, 911, 919, 929, 937, 941, 947,
1997 953, 967, 971, 977, 983, 991, 997, -103
1998};
1999
2000/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002001 * Small divisors test (X must be positive)
2002 *
2003 * Return values:
2004 * 0: no small factor (possible prime, more tests needed)
2005 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002006 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002007 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002008 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002009static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002010{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002011 int ret = 0;
2012 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002013 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002014
Paul Bakker5121ce52009-01-03 21:22:43 +00002015 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002017
2018 for( i = 0; small_prime[i] > 0; i++ )
2019 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002020 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002021 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002024
2025 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002026 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002027 }
2028
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002029cleanup:
2030 return( ret );
2031}
2032
2033/*
2034 * Miller-Rabin pseudo-primality test (HAC 4.24)
2035 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002036static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002037 int (*f_rng)(void *, unsigned char *, size_t),
2038 void *p_rng )
2039{
Pascal Junodb99183d2015-03-11 16:49:45 +01002040 int ret, count;
2041 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002042 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002044 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2045 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002046
Paul Bakker5121ce52009-01-03 21:22:43 +00002047 /*
2048 * W = |X| - 1
2049 * R = W >> lsb( W )
2050 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002051 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2052 s = mbedtls_mpi_lsb( &W );
2053 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2054 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002055
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002056 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002057 /*
2058 * HAC, table 4.4
2059 */
2060 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2061 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2062 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2063
2064 for( i = 0; i < n; i++ )
2065 {
2066 /*
2067 * pick a random A, 1 < A < |X| - 1
2068 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002069 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002070
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002071 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00002072 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002073 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002074 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00002075 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002076 A.p[0] |= 3;
2077
Pascal Junodb99183d2015-03-11 16:49:45 +01002078 count = 0;
2079 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002080 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002081
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002082 j = mbedtls_mpi_bitlen( &A );
2083 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002084 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002085 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002086 }
2087
2088 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002089 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002090 }
2091
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002092 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2093 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002094
2095 /*
2096 * A = A^R mod |X|
2097 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002098 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002099
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002100 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2101 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002102 continue;
2103
2104 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002105 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002106 {
2107 /*
2108 * A = A * A mod |X|
2109 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002110 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2111 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002113 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002114 break;
2115
2116 j++;
2117 }
2118
2119 /*
2120 * not prime if A != |X| - 1 or A == 1
2121 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002122 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2123 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002124 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002125 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002126 break;
2127 }
2128 }
2129
2130cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002131 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2132 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002133
2134 return( ret );
2135}
2136
2137/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002138 * Pseudo-primality test: small factors, then Miller-Rabin
2139 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002140int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002141 int (*f_rng)(void *, unsigned char *, size_t),
2142 void *p_rng )
2143{
2144 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002146
2147 XX.s = 1;
2148 XX.n = X->n;
2149 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002150
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002151 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2152 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2153 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002154
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002155 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002156 return( 0 );
2157
2158 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2159 {
2160 if( ret == 1 )
2161 return( 0 );
2162
2163 return( ret );
2164 }
2165
2166 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2167}
2168
2169/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002170 * Prime number generation
2171 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002172int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002173 int (*f_rng)(void *, unsigned char *, size_t),
2174 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002175{
Paul Bakker23986e52011-04-24 08:57:21 +00002176 int ret;
2177 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002178 mbedtls_mpi_uint r;
2179 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002181 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2182 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002185
2186 n = BITS_TO_LIMBS( nbits );
2187
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002189
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002190 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002191 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002192
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002193 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002194
2195 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002196
2197 if( dh_flag == 0 )
2198 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002199 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002200 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002201 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002202 goto cleanup;
2203
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002204 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002205 }
2206 }
2207 else
2208 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002209 /*
2210 * An necessary condition for Y and X = 2Y + 1 to be prime
2211 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2212 * Make sure it is satisfied, while keeping X = 3 mod 4
2213 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002214
2215 X->p[0] |= 2;
2216
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002217 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002218 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002219 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002220 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002221 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002222
2223 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002224 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2225 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002226
2227 while( 1 )
2228 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002229 /*
2230 * First, check small factors for X and Y
2231 * before doing Miller-Rabin on any of them
2232 */
2233 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2234 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2235 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2236 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002237 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002238 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002239 }
2240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002241 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002242 goto cleanup;
2243
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002244 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002245 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002246 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2247 * so up Y by 6 and X by 12.
2248 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002249 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2250 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002251 }
2252 }
2253
2254cleanup:
2255
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002256 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002257
2258 return( ret );
2259}
2260
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002261#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002262
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002263#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002264
Paul Bakker23986e52011-04-24 08:57:21 +00002265#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002266
2267static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2268{
2269 { 693, 609, 21 },
2270 { 1764, 868, 28 },
2271 { 768454923, 542167814, 1 }
2272};
2273
Paul Bakker5121ce52009-01-03 21:22:43 +00002274/*
2275 * Checkup routine
2276 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002277int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002278{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002279 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002280 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002281
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002282 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2283 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002284
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002285 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002286 "EFE021C2645FD1DC586E69184AF4A31E" \
2287 "D5F53E93B5F123FA41680867BA110131" \
2288 "944FE7952E2517337780CB0DB80E61AA" \
2289 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2290
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002291 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002292 "B2E7EFD37075B9F03FF989C7C5051C20" \
2293 "34D2A323810251127E7BF8625A4F49A5" \
2294 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2295 "5B5C25763222FEFCCFC38B832366C29E" ) );
2296
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002297 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002298 "0066A198186C18C10B2F5ED9B522752A" \
2299 "9830B69916E535C8F047518A889A43A5" \
2300 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2301
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002302 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002303
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002304 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002305 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2306 "9E857EA95A03512E2BAE7391688D264A" \
2307 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2308 "8001B72E848A38CAE1C65F78E56ABDEF" \
2309 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2310 "ECF677152EF804370C1A305CAF3B5BF1" \
2311 "30879B56C61DE584A0F53A2447A51E" ) );
2312
2313 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002314 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002315
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002316 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002317 {
2318 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002319 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002320
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002321 ret = 1;
2322 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002323 }
2324
2325 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002326 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002327
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002328 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002329
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002331 "256567336059E52CAE22925474705F39A94" ) );
2332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002333 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002334 "6613F26162223DF488E9CD48CC132C7A" \
2335 "0AC93C701B001B092E4E5B9F73BCD27B" \
2336 "9EE50D0657C77F374E903CDFA4C642" ) );
2337
2338 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002339 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2342 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002343 {
2344 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002345 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002347 ret = 1;
2348 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002349 }
2350
2351 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002352 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002354 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002355
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002356 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002357 "36E139AEA55215609D2816998ED020BB" \
2358 "BD96C37890F65171D948E9BC7CBAA4D9" \
2359 "325D24D6A3C12710F10A09FA08AB87" ) );
2360
2361 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002362 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002363
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002364 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002365 {
2366 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002368
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002369 ret = 1;
2370 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002371 }
2372
2373 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002374 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002375
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002378 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002379 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2380 "C3DBA76456363A10869622EAC2DD84EC" \
2381 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2382
2383 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002384 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002385
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002386 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002387 {
2388 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002389 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002390
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002391 ret = 1;
2392 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002393 }
2394
2395 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002397
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002398 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002399 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002400
Paul Bakker66d5d072014-06-17 16:39:18 +02002401 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002402 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002403 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2404 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002406 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002408 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002409 {
2410 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002411 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002412
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002413 ret = 1;
2414 goto cleanup;
2415 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002416 }
2417
2418 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002419 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002420
Paul Bakker5121ce52009-01-03 21:22:43 +00002421cleanup:
2422
2423 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002424 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002425
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002426 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2427 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002428
2429 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002430 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002431
2432 return( ret );
2433}
2434
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002435#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002436
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002437#endif /* MBEDTLS_BIGNUM_C */