blob: edf3737bb6bc540092c769481cea80a838aec998 [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
Hanno Becker88807112017-10-18 12:41:30 +010066/* Implementation that should never be optimized out by the compiler */
67static void mbedtls_zeroize( void *v, size_t n ) {
68 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
69}
70
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000072#define biL (ciL << 3) /* bits in limb */
73#define biH (ciL << 2) /* half limb size */
74
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010075#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
76
Paul Bakker5121ce52009-01-03 21:22:43 +000077/*
78 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020079 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000080 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020081#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
82#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000083
84/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000085 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000086 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020087void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000088{
Paul Bakker6c591fa2011-05-05 11:49:20 +000089 if( X == NULL )
90 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000091
Paul Bakker6c591fa2011-05-05 11:49:20 +000092 X->s = 1;
93 X->n = 0;
94 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000095}
96
97/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000098 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000099 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000101{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000102 if( X == NULL )
103 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000104
Paul Bakker6c591fa2011-05-05 11:49:20 +0000105 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000106 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200107 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200108 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000109 }
110
Paul Bakker6c591fa2011-05-05 11:49:20 +0000111 X->s = 1;
112 X->n = 0;
113 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000114}
115
116/*
117 * Enlarge to the specified number of limbs
118 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000120{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200123 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200124 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000125
Paul Bakker5121ce52009-01-03 21:22:43 +0000126 if( X->n < nblimbs )
127 {
Simon Butcher29176892016-05-20 00:19:09 +0100128 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200129 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000130
Paul Bakker5121ce52009-01-03 21:22:43 +0000131 if( X->p != NULL )
132 {
133 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200134 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000136 }
137
138 X->n = nblimbs;
139 X->p = p;
140 }
141
142 return( 0 );
143}
144
145/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100146 * Resize down as much as possible,
147 * while keeping at least the specified number of limbs
148 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100150{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152 size_t i;
153
154 /* Actually resize up in this case */
155 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100157
158 for( i = X->n - 1; i > 0; i-- )
159 if( X->p[i] != 0 )
160 break;
161 i++;
162
163 if( i < nblimbs )
164 i = nblimbs;
165
Simon Butcher29176892016-05-20 00:19:09 +0100166 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200167 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100168
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100169 if( X->p != NULL )
170 {
171 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200172 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100174 }
175
176 X->n = i;
177 X->p = p;
178
179 return( 0 );
180}
181
182/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000183 * Copy the contents of Y into X
184 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000186{
Paul Bakker23986e52011-04-24 08:57:21 +0000187 int ret;
188 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000189
190 if( X == Y )
191 return( 0 );
192
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200193 if( Y->p == NULL )
194 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200195 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200196 return( 0 );
197 }
198
Paul Bakker5121ce52009-01-03 21:22:43 +0000199 for( i = Y->n - 1; i > 0; i-- )
200 if( Y->p[i] != 0 )
201 break;
202 i++;
203
204 X->s = Y->s;
205
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000207
208 memset( X->p, 0, X->n * ciL );
209 memcpy( X->p, Y->p, i * ciL );
210
211cleanup:
212
213 return( ret );
214}
215
216/*
217 * Swap the contents of X and Y
218 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000220{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200223 memcpy( &T, X, sizeof( mbedtls_mpi ) );
224 memcpy( X, Y, sizeof( mbedtls_mpi ) );
225 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000226}
227
228/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100229 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100230 * about whether the assignment was made or not.
231 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100234{
235 int ret = 0;
236 size_t i;
237
Pascal Junodb99183d2015-03-11 16:49:45 +0100238 /* make sure assign is 0 or 1 in a time-constant manner */
239 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100242
Paul Bakker66d5d072014-06-17 16:39:18 +0200243 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100244
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100245 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200246 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100247
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100248 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200249 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250
251cleanup:
252 return( ret );
253}
254
255/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100256 * Conditionally swap X and Y, without leaking information
257 * about whether the swap was made or not.
258 * Here it is not ok to simply swap the pointers, which whould lead to
259 * different memory access patterns when X and Y are used afterwards.
260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100262{
263 int ret, s;
264 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100266
267 if( X == Y )
268 return( 0 );
269
Pascal Junodb99183d2015-03-11 16:49:45 +0100270 /* make sure swap is 0 or 1 in a time-constant manner */
271 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100272
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200273 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
274 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100275
276 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200277 X->s = X->s * ( 1 - swap ) + Y->s * swap;
278 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100279
280
281 for( i = 0; i < X->n; i++ )
282 {
283 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200284 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
285 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286 }
287
288cleanup:
289 return( ret );
290}
291
292/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000293 * Set value from integer
294 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200295int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000296{
297 int ret;
298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000300 memset( X->p, 0, X->n * ciL );
301
302 X->p[0] = ( z < 0 ) ? -z : z;
303 X->s = ( z < 0 ) ? -1 : 1;
304
305cleanup:
306
307 return( ret );
308}
309
310/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000311 * Get a specific bit
312 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200313int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000314{
315 if( X->n * biL <= pos )
316 return( 0 );
317
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200318 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000319}
320
Gilles Peskine220cc172018-11-20 16:47:47 +0100321/* Get a specific byte, without range checks. */
322#define GET_BYTE( X, i ) \
323 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
324
Paul Bakker2f5947e2011-05-18 15:47:11 +0000325/*
326 * Set a bit to a specific value of 0 or 1
327 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200328int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000329{
330 int ret = 0;
331 size_t off = pos / biL;
332 size_t idx = pos % biL;
333
334 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200335 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200336
Paul Bakker2f5947e2011-05-18 15:47:11 +0000337 if( X->n * biL <= pos )
338 {
339 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200340 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200342 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000343 }
344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200345 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
346 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000347
348cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200349
Paul Bakker2f5947e2011-05-18 15:47:11 +0000350 return( ret );
351}
352
353/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200354 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000355 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000357{
Paul Bakker23986e52011-04-24 08:57:21 +0000358 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000359
360 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000361 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000362 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
363 return( count );
364
365 return( 0 );
366}
367
368/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000369 * Count leading zero bits in a given integer
370 */
371static size_t mbedtls_clz( const mbedtls_mpi_uint x )
372{
373 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100374 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000375
376 for( j = 0; j < biL; j++ )
377 {
378 if( x & mask ) break;
379
380 mask >>= 1;
381 }
382
383 return j;
384}
385
386/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200387 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000388 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200389size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000390{
Paul Bakker23986e52011-04-24 08:57:21 +0000391 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000392
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200393 if( X->n == 0 )
394 return( 0 );
395
Paul Bakker5121ce52009-01-03 21:22:43 +0000396 for( i = X->n - 1; i > 0; i-- )
397 if( X->p[i] != 0 )
398 break;
399
Simon Butcher15b15d12015-11-26 19:35:03 +0000400 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000401
Paul Bakker23986e52011-04-24 08:57:21 +0000402 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000403}
404
405/*
406 * Return the total size in bytes
407 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000409{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200410 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000411}
412
413/*
414 * Convert an ASCII character to digit value
415 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000417{
418 *d = 255;
419
420 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
421 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
422 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424 if( *d >= (mbedtls_mpi_uint) radix )
425 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
427 return( 0 );
428}
429
430/*
431 * Import from an ASCII string
432 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000434{
Paul Bakker23986e52011-04-24 08:57:21 +0000435 int ret;
436 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437 mbedtls_mpi_uint d;
438 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000439
440 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200443 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000444
Paul Bakkerff60ee62010-03-16 21:09:09 +0000445 slen = strlen( s );
446
Paul Bakker5121ce52009-01-03 21:22:43 +0000447 if( radix == 16 )
448 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100449 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200450 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
451
Paul Bakkerff60ee62010-03-16 21:09:09 +0000452 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000453
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
455 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000456
Paul Bakker23986e52011-04-24 08:57:21 +0000457 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 {
Paul Bakker23986e52011-04-24 08:57:21 +0000459 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000460 {
461 X->s = -1;
462 break;
463 }
464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200466 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000467 }
468 }
469 else
470 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000472
Paul Bakkerff60ee62010-03-16 21:09:09 +0000473 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 {
475 if( i == 0 && s[i] == '-' )
476 {
477 X->s = -1;
478 continue;
479 }
480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
482 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000483
484 if( X->s == 1 )
485 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000487 }
488 else
489 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000491 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000492 }
493 }
494
495cleanup:
496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000498
499 return( ret );
500}
501
502/*
Ron Eldore6cbfc32018-11-20 14:07:01 +0200503 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000504 */
Ron Eldore6cbfc32018-11-20 14:07:01 +0200505static int mpi_write_hlp( mbedtls_mpi *X, int radix,
506 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000507{
508 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 mbedtls_mpi_uint r;
Ron Eldore6cbfc32018-11-20 14:07:01 +0200510 size_t length = 0;
511 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000512
Ron Eldore6cbfc32018-11-20 14:07:01 +0200513 do
514 {
515 if( length >= buflen )
516 {
517 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
518 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000519
Ron Eldore6cbfc32018-11-20 14:07:01 +0200520 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
521 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
522 /*
523 * Write the residue in the current position, as an ASCII character.
524 */
525 if( r < 0xA )
526 *(--p_end) = (char)( '0' + r );
527 else
528 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000529
Ron Eldore6cbfc32018-11-20 14:07:01 +0200530 length++;
531 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000532
Ron Eldore6cbfc32018-11-20 14:07:01 +0200533 memmove( *p, p_end, length );
534 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000535
536cleanup:
537
538 return( ret );
539}
540
541/*
542 * Export into an ASCII string
543 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100544int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
545 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000546{
Paul Bakker23986e52011-04-24 08:57:21 +0000547 int ret = 0;
548 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000549 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000551
552 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000554
Hanno Beckera277d4c2019-02-04 09:45:07 +0000555 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
556 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
557 * `n`. If radix > 4, this might be a strict
558 * overapproximation of the number of
559 * radix-adic digits needed to present `n`. */
560 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
561 * present `n`. */
562
Janos Follath216e7382019-03-06 13:43:02 +0000563 n += 1; /* Terminating null byte */
Hanno Beckera277d4c2019-02-04 09:45:07 +0000564 n += 1; /* Compensate for the divisions above, which round down `n`
565 * in case it's not even. */
566 n += 1; /* Potential '-'-sign. */
567 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
568 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000569
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100570 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000571 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100572 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000574 }
575
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100576 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000578
579 if( X->s == -1 )
Hanno Beckereff335d2019-02-01 16:41:30 +0000580 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000581 *p++ = '-';
Hanno Beckereff335d2019-02-01 16:41:30 +0000582 buflen--;
583 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
585 if( radix == 16 )
586 {
Paul Bakker23986e52011-04-24 08:57:21 +0000587 int c;
588 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000589
Paul Bakker23986e52011-04-24 08:57:21 +0000590 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000591 {
Paul Bakker23986e52011-04-24 08:57:21 +0000592 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000593 {
Paul Bakker23986e52011-04-24 08:57:21 +0000594 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000595
Paul Bakker6c343d72014-07-10 14:36:19 +0200596 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000597 continue;
598
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000599 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000600 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000601 k = 1;
602 }
603 }
604 }
605 else
606 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000608
609 if( T.s == -1 )
610 T.s = 1;
611
Ron Eldore6cbfc32018-11-20 14:07:01 +0200612 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000613 }
614
615 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100616 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000617
618cleanup:
619
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000621
622 return( ret );
623}
624
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200625#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000626/*
627 * Read X from an opened file
628 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000630{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000632 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000633 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000634 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000635 * Buffer should have space for (short) label and decimal formatted MPI,
636 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000637 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000639
640 memset( s, 0, sizeof( s ) );
641 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000643
644 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000645 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200646 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000647
Hanno Beckerb2034b72017-04-26 11:46:46 +0100648 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
649 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000650
651 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100652 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000653 if( mpi_get_digit( &d, radix, *p ) != 0 )
654 break;
655
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000657}
658
659/*
660 * Write X into an opened file (or stdout if fout == NULL)
661 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000663{
Paul Bakker23986e52011-04-24 08:57:21 +0000664 int ret;
665 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000666 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000667 * Buffer should have space for (short) label and decimal formatted MPI,
668 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000669 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000671
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100672 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000673
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100674 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000675
676 if( p == NULL ) p = "";
677
678 plen = strlen( p );
679 slen = strlen( s );
680 s[slen++] = '\r';
681 s[slen++] = '\n';
682
683 if( fout != NULL )
684 {
685 if( fwrite( p, 1, plen, fout ) != plen ||
686 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000688 }
689 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
692cleanup:
693
694 return( ret );
695}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000697
698/*
699 * Import X from unsigned binary data, big endian
700 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000702{
Paul Bakker23986e52011-04-24 08:57:21 +0000703 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100704 size_t i, j;
705 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000706
Hanno Becker073c1992017-10-17 15:17:27 +0100707 /* Ensure that target MPI has exactly the necessary number of limbs */
708 if( X->n != limbs )
709 {
710 mbedtls_mpi_free( X );
711 mbedtls_mpi_init( X );
712 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
713 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000714
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200715 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000716
Hanno Becker073c1992017-10-17 15:17:27 +0100717 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200718 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000719
720cleanup:
721
722 return( ret );
723}
724
725/*
726 * Export X into unsigned binary data, big endian
727 */
Gilles Peskine220cc172018-11-20 16:47:47 +0100728int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
729 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000730{
Gilles Peskine220cc172018-11-20 16:47:47 +0100731 size_t stored_bytes = X->n * ciL;
732 size_t bytes_to_copy;
733 unsigned char *p;
734 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000735
Gilles Peskine220cc172018-11-20 16:47:47 +0100736 if( stored_bytes < buflen )
737 {
738 /* There is enough space in the output buffer. Write initial
739 * null bytes and record the position at which to start
740 * writing the significant bytes. In this case, the execution
741 * trace of this function does not depend on the value of the
742 * number. */
743 bytes_to_copy = stored_bytes;
744 p = buf + buflen - stored_bytes;
745 memset( buf, 0, buflen - stored_bytes );
746 }
747 else
748 {
749 /* The output buffer is smaller than the allocated size of X.
750 * However X may fit if its leading bytes are zero. */
751 bytes_to_copy = buflen;
752 p = buf;
753 for( i = bytes_to_copy; i < stored_bytes; i++ )
754 {
755 if( GET_BYTE( X, i ) != 0 )
756 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
757 }
758 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000759
Gilles Peskine220cc172018-11-20 16:47:47 +0100760 for( i = 0; i < bytes_to_copy; i++ )
761 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000762
763 return( 0 );
764}
765
766/*
767 * Left-shift: X <<= count
768 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200769int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000770{
Paul Bakker23986e52011-04-24 08:57:21 +0000771 int ret;
772 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200773 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000774
775 v0 = count / (biL );
776 t1 = count & (biL - 1);
777
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200778 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000779
Paul Bakkerf9688572011-05-05 10:00:45 +0000780 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200781 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000782
783 ret = 0;
784
785 /*
786 * shift by count / limb_size
787 */
788 if( v0 > 0 )
789 {
Paul Bakker23986e52011-04-24 08:57:21 +0000790 for( i = X->n; i > v0; i-- )
791 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000792
Paul Bakker23986e52011-04-24 08:57:21 +0000793 for( ; i > 0; i-- )
794 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000795 }
796
797 /*
798 * shift by count % limb_size
799 */
800 if( t1 > 0 )
801 {
802 for( i = v0; i < X->n; i++ )
803 {
804 r1 = X->p[i] >> (biL - t1);
805 X->p[i] <<= t1;
806 X->p[i] |= r0;
807 r0 = r1;
808 }
809 }
810
811cleanup:
812
813 return( ret );
814}
815
816/*
817 * Right-shift: X >>= count
818 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200819int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000820{
Paul Bakker23986e52011-04-24 08:57:21 +0000821 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200822 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000823
824 v0 = count / biL;
825 v1 = count & (biL - 1);
826
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100827 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200828 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100829
Paul Bakker5121ce52009-01-03 21:22:43 +0000830 /*
831 * shift by count / limb_size
832 */
833 if( v0 > 0 )
834 {
835 for( i = 0; i < X->n - v0; i++ )
836 X->p[i] = X->p[i + v0];
837
838 for( ; i < X->n; i++ )
839 X->p[i] = 0;
840 }
841
842 /*
843 * shift by count % limb_size
844 */
845 if( v1 > 0 )
846 {
Paul Bakker23986e52011-04-24 08:57:21 +0000847 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000848 {
Paul Bakker23986e52011-04-24 08:57:21 +0000849 r1 = X->p[i - 1] << (biL - v1);
850 X->p[i - 1] >>= v1;
851 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000852 r0 = r1;
853 }
854 }
855
856 return( 0 );
857}
858
859/*
860 * Compare unsigned values
861 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200862int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000863{
Paul Bakker23986e52011-04-24 08:57:21 +0000864 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000865
Paul Bakker23986e52011-04-24 08:57:21 +0000866 for( i = X->n; i > 0; i-- )
867 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000868 break;
869
Paul Bakker23986e52011-04-24 08:57:21 +0000870 for( j = Y->n; j > 0; j-- )
871 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000872 break;
873
Paul Bakker23986e52011-04-24 08:57:21 +0000874 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000875 return( 0 );
876
877 if( i > j ) return( 1 );
878 if( j > i ) return( -1 );
879
Paul Bakker23986e52011-04-24 08:57:21 +0000880 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000881 {
Paul Bakker23986e52011-04-24 08:57:21 +0000882 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
883 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000884 }
885
886 return( 0 );
887}
888
889/*
890 * Compare signed values
891 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200892int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000893{
Paul Bakker23986e52011-04-24 08:57:21 +0000894 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000895
Paul Bakker23986e52011-04-24 08:57:21 +0000896 for( i = X->n; i > 0; i-- )
897 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000898 break;
899
Paul Bakker23986e52011-04-24 08:57:21 +0000900 for( j = Y->n; j > 0; j-- )
901 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000902 break;
903
Paul Bakker23986e52011-04-24 08:57:21 +0000904 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000905 return( 0 );
906
907 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000908 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000909
910 if( X->s > 0 && Y->s < 0 ) return( 1 );
911 if( Y->s > 0 && X->s < 0 ) return( -1 );
912
Paul Bakker23986e52011-04-24 08:57:21 +0000913 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000914 {
Paul Bakker23986e52011-04-24 08:57:21 +0000915 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
916 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000917 }
918
919 return( 0 );
920}
921
Janos Follath3173a532019-10-14 09:09:32 +0100922/** Decide if an integer is less than the other, without branches.
923 *
924 * \param x First integer.
925 * \param y Second integer.
926 *
927 * \return 1 if \p x is less than \p y, 0 otherwise
928 */
Janos Follathc3b376e2019-10-11 14:21:53 +0100929static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
930 const mbedtls_mpi_uint y )
Janos Follathe0187b92019-09-05 14:47:19 +0100931{
932 mbedtls_mpi_uint ret;
933 mbedtls_mpi_uint cond;
934
935 /*
936 * Check if the most significant bits (MSB) of the operands are different.
937 */
938 cond = ( x ^ y );
939 /*
940 * If the MSB are the same then the difference x-y will be negative (and
941 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
942 */
943 ret = ( x - y ) & ~cond;
944 /*
945 * If the MSB are different, then the operand with the MSB of 1 is the
946 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
947 * the MSB of y is 0.)
948 */
949 ret |= y & cond;
950
951
Janos Follathdb9f4492019-10-14 08:59:14 +0100952 ret = ret >> ( biL - 1 );
Janos Follathe0187b92019-09-05 14:47:19 +0100953
954 return ret;
955}
956
957/*
958 * Compare signed values in constant time
959 */
Janos Follathc3b376e2019-10-11 14:21:53 +0100960int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
961 unsigned *ret )
Janos Follathe0187b92019-09-05 14:47:19 +0100962{
963 size_t i;
Janos Follath782cbe52019-10-14 09:01:15 +0100964 unsigned cond, done, sign_X, sign_Y;
Janos Follathe0187b92019-09-05 14:47:19 +0100965
966 if( X->n != Y->n )
967 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
968
969 /*
Janos Follath51ed14e2019-10-28 12:12:15 +0000970 * Set sign_N to 1 if N >= 0, 0 if N < 0.
971 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathe0187b92019-09-05 14:47:19 +0100972 */
Janos Follath51ed14e2019-10-28 12:12:15 +0000973 sign_X = ( X->s & 2 ) >> 1;
974 sign_Y = ( Y->s & 2 ) >> 1;
Janos Follathc3b376e2019-10-11 14:21:53 +0100975
976 /*
977 * If the signs are different, then the positive operand is the bigger.
978 * That is if X is negative (sign bit 1), then X < Y is true and it is false
979 * if X is positive (sign bit 0).
980 */
981 cond = ( sign_X ^ sign_Y );
982 *ret = cond & sign_X;
983
984 /*
985 * This is a constant time function, we might have the result, but we still
986 * need to go through the loop. Record if we have the result already.
987 */
Janos Follathe0187b92019-09-05 14:47:19 +0100988 done = cond;
989
990 for( i = X->n; i > 0; i-- )
991 {
992 /*
Janos Follathc3b376e2019-10-11 14:21:53 +0100993 * If Y->p[i - 1] < X->p[i - 1] and both X and Y are negative, then
994 * X < Y.
995 *
996 * Again even if we can make a decision, we just mark the result and
997 * the fact that we are done and continue looping.
Janos Follathe0187b92019-09-05 14:47:19 +0100998 */
Janos Follathc3b376e2019-10-11 14:21:53 +0100999 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] ) & sign_X;
1000 *ret |= cond & ( 1 - done );
Janos Follath8461c0e2019-10-11 10:43:40 +01001001 done |= cond & ( 1 - done );
Janos Follathe0187b92019-09-05 14:47:19 +01001002
1003 /*
Janos Follathc3b376e2019-10-11 14:21:53 +01001004 * If X->p[i - 1] < Y->p[i - 1] and both X and Y are positive, then
1005 * X < Y.
1006 *
1007 * Again even if we can make a decision, we just mark the result and
1008 * the fact that we are done and continue looping.
Janos Follathe0187b92019-09-05 14:47:19 +01001009 */
Janos Follathc3b376e2019-10-11 14:21:53 +01001010 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] ) & ( 1 - sign_X );
1011 *ret |= cond & ( 1 - done );
Janos Follath8461c0e2019-10-11 10:43:40 +01001012 done |= cond & ( 1 - done );
Janos Follathe0187b92019-09-05 14:47:19 +01001013 }
1014
1015 return( 0 );
1016}
1017
Paul Bakker5121ce52009-01-03 21:22:43 +00001018/*
1019 * Compare signed values
1020 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001021int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001022{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001023 mbedtls_mpi Y;
1024 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001025
1026 *p = ( z < 0 ) ? -z : z;
1027 Y.s = ( z < 0 ) ? -1 : 1;
1028 Y.n = 1;
1029 Y.p = p;
1030
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001031 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001032}
1033
1034/*
1035 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1036 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001037int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001038{
Paul Bakker23986e52011-04-24 08:57:21 +00001039 int ret;
1040 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001041 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +00001042
1043 if( X == B )
1044 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001045 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001046 }
1047
1048 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001049 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001050
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001051 /*
1052 * X should always be positive as a result of unsigned additions.
1053 */
1054 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001055
Paul Bakker23986e52011-04-24 08:57:21 +00001056 for( j = B->n; j > 0; j-- )
1057 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001058 break;
1059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001060 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001061
1062 o = B->p; p = X->p; c = 0;
1063
Janos Follath6c922682015-10-30 17:43:11 +01001064 /*
1065 * tmp is used because it might happen that p == o
1066 */
Paul Bakker23986e52011-04-24 08:57:21 +00001067 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001068 {
Janos Follath6c922682015-10-30 17:43:11 +01001069 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001070 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001071 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001072 }
1073
1074 while( c != 0 )
1075 {
1076 if( i >= X->n )
1077 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001078 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001079 p = X->p + i;
1080 }
1081
Paul Bakker2d319fd2012-09-16 21:34:26 +00001082 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001083 }
1084
1085cleanup:
1086
1087 return( ret );
1088}
1089
1090/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001091 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001092 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001093static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001094{
Paul Bakker23986e52011-04-24 08:57:21 +00001095 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001096 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001097
1098 for( i = c = 0; i < n; i++, s++, d++ )
1099 {
1100 z = ( *d < c ); *d -= c;
1101 c = ( *d < *s ) + z; *d -= *s;
1102 }
1103
1104 while( c != 0 )
1105 {
1106 z = ( *d < c ); *d -= c;
1107 c = z; i++; d++;
1108 }
1109}
1110
1111/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001112 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001113 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001114int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001115{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001116 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001117 int ret;
1118 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001120 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1121 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001123 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001124
1125 if( X == B )
1126 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001127 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001128 B = &TB;
1129 }
1130
1131 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001132 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001133
Paul Bakker1ef7a532009-06-20 10:50:55 +00001134 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001135 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001136 */
1137 X->s = 1;
1138
Paul Bakker5121ce52009-01-03 21:22:43 +00001139 ret = 0;
1140
Paul Bakker23986e52011-04-24 08:57:21 +00001141 for( n = B->n; n > 0; n-- )
1142 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001143 break;
1144
Paul Bakker23986e52011-04-24 08:57:21 +00001145 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001146
1147cleanup:
1148
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001149 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001150
1151 return( ret );
1152}
1153
1154/*
1155 * Signed addition: X = A + B
1156 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001157int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001158{
1159 int ret, s = A->s;
1160
1161 if( A->s * B->s < 0 )
1162 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001163 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001164 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001165 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001166 X->s = s;
1167 }
1168 else
1169 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001170 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001171 X->s = -s;
1172 }
1173 }
1174 else
1175 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001176 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001177 X->s = s;
1178 }
1179
1180cleanup:
1181
1182 return( ret );
1183}
1184
1185/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001186 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001187 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001188int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001189{
1190 int ret, s = A->s;
1191
1192 if( A->s * B->s > 0 )
1193 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001194 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001195 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001196 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001197 X->s = s;
1198 }
1199 else
1200 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001201 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001202 X->s = -s;
1203 }
1204 }
1205 else
1206 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001207 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001208 X->s = s;
1209 }
1210
1211cleanup:
1212
1213 return( ret );
1214}
1215
1216/*
1217 * Signed addition: X = A + b
1218 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001219int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001220{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001221 mbedtls_mpi _B;
1222 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001223
1224 p[0] = ( b < 0 ) ? -b : b;
1225 _B.s = ( b < 0 ) ? -1 : 1;
1226 _B.n = 1;
1227 _B.p = p;
1228
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001229 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001230}
1231
1232/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001233 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001234 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001235int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001236{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001237 mbedtls_mpi _B;
1238 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001239
1240 p[0] = ( b < 0 ) ? -b : b;
1241 _B.s = ( b < 0 ) ? -1 : 1;
1242 _B.n = 1;
1243 _B.p = p;
1244
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001245 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001246}
1247
1248/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001249 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001250 */
1251static
1252#if defined(__APPLE__) && defined(__arm__)
1253/*
1254 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1255 * appears to need this to prevent bad ARM code generation at -O3.
1256 */
1257__attribute__ ((noinline))
1258#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001259void 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 +00001260{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001261 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001262
1263#if defined(MULADDC_HUIT)
1264 for( ; i >= 8; i -= 8 )
1265 {
1266 MULADDC_INIT
1267 MULADDC_HUIT
1268 MULADDC_STOP
1269 }
1270
1271 for( ; i > 0; i-- )
1272 {
1273 MULADDC_INIT
1274 MULADDC_CORE
1275 MULADDC_STOP
1276 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001277#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001278 for( ; i >= 16; i -= 16 )
1279 {
1280 MULADDC_INIT
1281 MULADDC_CORE MULADDC_CORE
1282 MULADDC_CORE MULADDC_CORE
1283 MULADDC_CORE MULADDC_CORE
1284 MULADDC_CORE MULADDC_CORE
1285
1286 MULADDC_CORE MULADDC_CORE
1287 MULADDC_CORE MULADDC_CORE
1288 MULADDC_CORE MULADDC_CORE
1289 MULADDC_CORE MULADDC_CORE
1290 MULADDC_STOP
1291 }
1292
1293 for( ; i >= 8; i -= 8 )
1294 {
1295 MULADDC_INIT
1296 MULADDC_CORE MULADDC_CORE
1297 MULADDC_CORE MULADDC_CORE
1298
1299 MULADDC_CORE MULADDC_CORE
1300 MULADDC_CORE MULADDC_CORE
1301 MULADDC_STOP
1302 }
1303
1304 for( ; i > 0; i-- )
1305 {
1306 MULADDC_INIT
1307 MULADDC_CORE
1308 MULADDC_STOP
1309 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001310#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001311
1312 t++;
1313
1314 do {
1315 *d += c; c = ( *d < c ); d++;
1316 }
1317 while( c != 0 );
1318}
1319
1320/*
1321 * Baseline multiplication: X = A * B (HAC 14.12)
1322 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001323int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001324{
Paul Bakker23986e52011-04-24 08:57:21 +00001325 int ret;
1326 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001327 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001329 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001330
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001331 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1332 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001333
Paul Bakker23986e52011-04-24 08:57:21 +00001334 for( i = A->n; i > 0; i-- )
1335 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001336 break;
1337
Paul Bakker23986e52011-04-24 08:57:21 +00001338 for( j = B->n; j > 0; j-- )
1339 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001340 break;
1341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001342 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1343 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001344
Paul Bakker23986e52011-04-24 08:57:21 +00001345 for( i++; j > 0; j-- )
1346 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001347
1348 X->s = A->s * B->s;
1349
1350cleanup:
1351
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001352 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001353
1354 return( ret );
1355}
1356
1357/*
1358 * Baseline multiplication: X = A * b
1359 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001360int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001361{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001362 mbedtls_mpi _B;
1363 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001364
1365 _B.s = 1;
1366 _B.n = 1;
1367 _B.p = p;
1368 p[0] = b;
1369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001370 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001371}
1372
1373/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001374 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1375 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001376 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001377static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1378 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001379{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001380#if defined(MBEDTLS_HAVE_UDBL)
1381 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001382#else
Simon Butcher9803d072016-01-03 00:24:34 +00001383 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1384 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001385 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1386 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001387 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001388#endif
1389
Simon Butcher15b15d12015-11-26 19:35:03 +00001390 /*
1391 * Check for overflow
1392 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001393 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001394 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001395 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001396
Simon Butcherf5ba0452015-12-27 23:01:55 +00001397 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001398 }
1399
1400#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001401 dividend = (mbedtls_t_udbl) u1 << biL;
1402 dividend |= (mbedtls_t_udbl) u0;
1403 quotient = dividend / d;
1404 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1405 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1406
1407 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001408 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001409
1410 return (mbedtls_mpi_uint) quotient;
1411#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001412
1413 /*
1414 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1415 * Vol. 2 - Seminumerical Algorithms, Knuth
1416 */
1417
1418 /*
1419 * Normalize the divisor, d, and dividend, u0, u1
1420 */
1421 s = mbedtls_clz( d );
1422 d = d << s;
1423
1424 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001425 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001426 u0 = u0 << s;
1427
1428 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001429 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001430
1431 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001432 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001433
1434 /*
1435 * Find the first quotient and remainder
1436 */
1437 q1 = u1 / d1;
1438 r0 = u1 - d1 * q1;
1439
1440 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1441 {
1442 q1 -= 1;
1443 r0 += d1;
1444
1445 if ( r0 >= radix ) break;
1446 }
1447
Simon Butcherf5ba0452015-12-27 23:01:55 +00001448 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001449 q0 = rAX / d1;
1450 r0 = rAX - q0 * d1;
1451
1452 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1453 {
1454 q0 -= 1;
1455 r0 += d1;
1456
1457 if ( r0 >= radix ) break;
1458 }
1459
1460 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001461 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001462
1463 quotient = q1 * radix + q0;
1464
1465 return quotient;
1466#endif
1467}
1468
1469/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001470 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001471 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001472int 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 +00001473{
Paul Bakker23986e52011-04-24 08:57:21 +00001474 int ret;
1475 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001476 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001477
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001478 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1479 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001481 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1482 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001484 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001485 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001486 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1487 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001488 return( 0 );
1489 }
1490
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001491 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1492 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001493 X.s = Y.s = 1;
1494
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001495 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1496 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1497 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1498 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001499
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001500 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001501 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001502 {
1503 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001504 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1505 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001506 }
1507 else k = 0;
1508
1509 n = X.n - 1;
1510 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001513 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001514 {
1515 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001516 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001517 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001518 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001519
1520 for( i = n; i > t ; i-- )
1521 {
1522 if( X.p[i] >= Y.p[t] )
1523 Z.p[i - t - 1] = ~0;
1524 else
1525 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001526 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1527 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001528 }
1529
1530 Z.p[i - t - 1]++;
1531 do
1532 {
1533 Z.p[i - t - 1]--;
1534
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001535 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001536 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001537 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001538 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001539
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001540 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001541 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1542 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001543 T2.p[2] = X.p[i];
1544 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001545 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001546
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001547 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1548 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1549 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001550
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001551 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001552 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001553 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1554 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1555 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001556 Z.p[i - t - 1]--;
1557 }
1558 }
1559
1560 if( Q != NULL )
1561 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001562 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001563 Q->s = A->s * B->s;
1564 }
1565
1566 if( R != NULL )
1567 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001568 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001569 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001570 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001571
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001572 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001573 R->s = 1;
1574 }
1575
1576cleanup:
1577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001578 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1579 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001580
1581 return( ret );
1582}
1583
1584/*
1585 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001586 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001587int 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 +00001588{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001589 mbedtls_mpi _B;
1590 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001591
1592 p[0] = ( b < 0 ) ? -b : b;
1593 _B.s = ( b < 0 ) ? -1 : 1;
1594 _B.n = 1;
1595 _B.p = p;
1596
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001597 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001598}
1599
1600/*
1601 * Modulo: R = A mod B
1602 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001603int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001604{
1605 int ret;
1606
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001607 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1608 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001609
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001610 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001612 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1613 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001615 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1616 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001617
1618cleanup:
1619
1620 return( ret );
1621}
1622
1623/*
1624 * Modulo: r = A mod b
1625 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001626int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001627{
Paul Bakker23986e52011-04-24 08:57:21 +00001628 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001629 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001630
1631 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001632 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001633
1634 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001635 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001636
1637 /*
1638 * handle trivial cases
1639 */
1640 if( b == 1 )
1641 {
1642 *r = 0;
1643 return( 0 );
1644 }
1645
1646 if( b == 2 )
1647 {
1648 *r = A->p[0] & 1;
1649 return( 0 );
1650 }
1651
1652 /*
1653 * general case
1654 */
Paul Bakker23986e52011-04-24 08:57:21 +00001655 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001656 {
Paul Bakker23986e52011-04-24 08:57:21 +00001657 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001658 y = ( y << biH ) | ( x >> biH );
1659 z = y / b;
1660 y -= z * b;
1661
1662 x <<= biH;
1663 y = ( y << biH ) | ( x >> biH );
1664 z = y / b;
1665 y -= z * b;
1666 }
1667
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001668 /*
1669 * If A is negative, then the current y represents a negative value.
1670 * Flipping it to the positive side.
1671 */
1672 if( A->s < 0 && y != 0 )
1673 y = b - y;
1674
Paul Bakker5121ce52009-01-03 21:22:43 +00001675 *r = y;
1676
1677 return( 0 );
1678}
1679
1680/*
1681 * Fast Montgomery initialization (thanks to Tom St Denis)
1682 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001683static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001684{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001685 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001686 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001687
1688 x = m0;
1689 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001690
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001691 for( i = biL; i >= 8; i /= 2 )
1692 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001693
1694 *mm = ~x + 1;
1695}
1696
1697/*
1698 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1699 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001700static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001701 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001702{
Paul Bakker23986e52011-04-24 08:57:21 +00001703 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001704 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001705
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001706 if( T->n < N->n + 1 || T->p == NULL )
1707 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1708
Paul Bakker5121ce52009-01-03 21:22:43 +00001709 memset( T->p, 0, T->n * ciL );
1710
1711 d = T->p;
1712 n = N->n;
1713 m = ( B->n < n ) ? B->n : n;
1714
1715 for( i = 0; i < n; i++ )
1716 {
1717 /*
1718 * T = (T + u0*B + u1*N) / 2^biL
1719 */
1720 u0 = A->p[i];
1721 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1722
1723 mpi_mul_hlp( m, B->p, d, u0 );
1724 mpi_mul_hlp( n, N->p, d, u1 );
1725
1726 *d++ = u0; d[n + 1] = 0;
1727 }
1728
Paul Bakker66d5d072014-06-17 16:39:18 +02001729 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001730
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001731 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001732 mpi_sub_hlp( n, N->p, A->p );
1733 else
1734 /* prevent timing attacks */
1735 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001736
1737 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001738}
1739
1740/*
1741 * Montgomery reduction: A = A * R^-1 mod N
1742 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001743static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001744{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001745 mbedtls_mpi_uint z = 1;
1746 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001747
Paul Bakker8ddb6452013-02-27 14:56:33 +01001748 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001749 U.p = &z;
1750
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001751 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001752}
1753
1754/*
1755 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1756 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001757int 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 +00001758{
Paul Bakker23986e52011-04-24 08:57:21 +00001759 int ret;
1760 size_t wbits, wsize, one = 1;
1761 size_t i, j, nblimbs;
1762 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001763 mbedtls_mpi_uint ei, mm, state;
1764 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001765 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001766
Hanno Becker930ec7d2018-03-09 10:48:00 +00001767 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001768 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001769
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001770 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1771 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001772
1773 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001774 * Init temps and window size
1775 */
1776 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001777 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1778 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001779 memset( W, 0, sizeof( W ) );
1780
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001781 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001782
1783 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1784 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1785
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001786#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001787 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1788 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001789#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001790
Paul Bakker5121ce52009-01-03 21:22:43 +00001791 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001792 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1793 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1794 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001795
1796 /*
Paul Bakker50546922012-05-19 08:40:49 +00001797 * Compensate for negative A (and correct at the end)
1798 */
1799 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001800 if( neg )
1801 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001802 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001803 Apos.s = 1;
1804 A = &Apos;
1805 }
1806
1807 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001808 * If 1st call, pre-compute R^2 mod N
1809 */
1810 if( _RR == NULL || _RR->p == NULL )
1811 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001812 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1813 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1814 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001815
1816 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001817 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001818 }
1819 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001820 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001821
1822 /*
1823 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1824 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001825 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1826 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001827 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001828 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001829
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001830 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001831
1832 /*
1833 * X = R^2 * R^-1 mod N = R mod N
1834 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001835 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001836 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001837
1838 if( wsize > 1 )
1839 {
1840 /*
1841 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1842 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001843 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001844
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001845 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1846 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001847
1848 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001849 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001850
Paul Bakker5121ce52009-01-03 21:22:43 +00001851 /*
1852 * W[i] = W[i - 1] * W[1]
1853 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001854 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001855 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001856 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1857 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001858
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001859 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001860 }
1861 }
1862
1863 nblimbs = E->n;
1864 bufsize = 0;
1865 nbits = 0;
1866 wbits = 0;
1867 state = 0;
1868
1869 while( 1 )
1870 {
1871 if( bufsize == 0 )
1872 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001873 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001874 break;
1875
Paul Bakker0d7702c2013-10-29 16:18:35 +01001876 nblimbs--;
1877
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001878 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001879 }
1880
1881 bufsize--;
1882
1883 ei = (E->p[nblimbs] >> bufsize) & 1;
1884
1885 /*
1886 * skip leading 0s
1887 */
1888 if( ei == 0 && state == 0 )
1889 continue;
1890
1891 if( ei == 0 && state == 1 )
1892 {
1893 /*
1894 * out of window, square X
1895 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001896 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001897 continue;
1898 }
1899
1900 /*
1901 * add ei to current window
1902 */
1903 state = 2;
1904
1905 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001906 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001907
1908 if( nbits == wsize )
1909 {
1910 /*
1911 * X = X^wsize R^-1 mod N
1912 */
1913 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001914 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001915
1916 /*
1917 * X = X * W[wbits] R^-1 mod N
1918 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001919 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001920
1921 state--;
1922 nbits = 0;
1923 wbits = 0;
1924 }
1925 }
1926
1927 /*
1928 * process the remaining bits
1929 */
1930 for( i = 0; i < nbits; i++ )
1931 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001932 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001933
1934 wbits <<= 1;
1935
Paul Bakker66d5d072014-06-17 16:39:18 +02001936 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001937 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001938 }
1939
1940 /*
1941 * X = A^E * R * R^-1 mod N = A^E mod N
1942 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001943 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001944
Hanno Beckera4af1c42017-04-18 09:07:45 +01001945 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001946 {
1947 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001948 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001949 }
1950
Paul Bakker5121ce52009-01-03 21:22:43 +00001951cleanup:
1952
Paul Bakker66d5d072014-06-17 16:39:18 +02001953 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001954 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001955
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001956 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001957
Paul Bakker75a28602014-03-31 12:08:17 +02001958 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001960
1961 return( ret );
1962}
1963
Paul Bakker5121ce52009-01-03 21:22:43 +00001964/*
1965 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1966 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001967int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001968{
Paul Bakker23986e52011-04-24 08:57:21 +00001969 int ret;
1970 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001971 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001972
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001973 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001974
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001975 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1976 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001977
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001978 lz = mbedtls_mpi_lsb( &TA );
1979 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001980
Paul Bakker66d5d072014-06-17 16:39:18 +02001981 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001982 lz = lzt;
1983
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001984 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1985 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001986
Paul Bakker5121ce52009-01-03 21:22:43 +00001987 TA.s = TB.s = 1;
1988
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001989 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001990 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001991 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1992 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001993
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001994 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001995 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001996 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1997 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001998 }
1999 else
2000 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002001 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2002 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002003 }
2004 }
2005
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002006 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2007 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002008
2009cleanup:
2010
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002011 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002012
2013 return( ret );
2014}
2015
Paul Bakker33dc46b2014-04-30 16:11:39 +02002016/*
2017 * Fill X with size bytes of random.
2018 *
2019 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002020 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002021 * deterministic, eg for tests).
2022 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002024 int (*f_rng)(void *, unsigned char *, size_t),
2025 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002026{
Paul Bakker23986e52011-04-24 08:57:21 +00002027 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002028 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02002029
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002030 if( size > MBEDTLS_MPI_MAX_SIZE )
2031 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002032
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002033 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2034 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002035
2036cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01002037 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002038 return( ret );
2039}
2040
Paul Bakker5121ce52009-01-03 21:22:43 +00002041/*
2042 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2043 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002044int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002045{
2046 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002047 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002048
Hanno Becker4bcb4912017-04-18 15:49:39 +01002049 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002050 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002051
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2053 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2054 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002055
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002056 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002057
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002059 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002061 goto cleanup;
2062 }
2063
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002064 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2065 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2066 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2067 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002068
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002069 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2070 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2071 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2072 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002073
2074 do
2075 {
2076 while( ( TU.p[0] & 1 ) == 0 )
2077 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002078 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002079
2080 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2081 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002082 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2083 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002084 }
2085
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002086 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2087 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002088 }
2089
2090 while( ( TV.p[0] & 1 ) == 0 )
2091 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002092 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002093
2094 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2095 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002096 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2097 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002098 }
2099
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002100 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2101 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002102 }
2103
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002104 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002105 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002106 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2107 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2108 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002109 }
2110 else
2111 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002112 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2113 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2114 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002115 }
2116 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002117 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002119 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2120 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002121
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002122 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2123 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002125 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002126
2127cleanup:
2128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002129 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2130 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2131 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002132
2133 return( ret );
2134}
2135
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002136#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002137
Paul Bakker5121ce52009-01-03 21:22:43 +00002138static const int small_prime[] =
2139{
2140 3, 5, 7, 11, 13, 17, 19, 23,
2141 29, 31, 37, 41, 43, 47, 53, 59,
2142 61, 67, 71, 73, 79, 83, 89, 97,
2143 101, 103, 107, 109, 113, 127, 131, 137,
2144 139, 149, 151, 157, 163, 167, 173, 179,
2145 181, 191, 193, 197, 199, 211, 223, 227,
2146 229, 233, 239, 241, 251, 257, 263, 269,
2147 271, 277, 281, 283, 293, 307, 311, 313,
2148 317, 331, 337, 347, 349, 353, 359, 367,
2149 373, 379, 383, 389, 397, 401, 409, 419,
2150 421, 431, 433, 439, 443, 449, 457, 461,
2151 463, 467, 479, 487, 491, 499, 503, 509,
2152 521, 523, 541, 547, 557, 563, 569, 571,
2153 577, 587, 593, 599, 601, 607, 613, 617,
2154 619, 631, 641, 643, 647, 653, 659, 661,
2155 673, 677, 683, 691, 701, 709, 719, 727,
2156 733, 739, 743, 751, 757, 761, 769, 773,
2157 787, 797, 809, 811, 821, 823, 827, 829,
2158 839, 853, 857, 859, 863, 877, 881, 883,
2159 887, 907, 911, 919, 929, 937, 941, 947,
2160 953, 967, 971, 977, 983, 991, 997, -103
2161};
2162
2163/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002164 * Small divisors test (X must be positive)
2165 *
2166 * Return values:
2167 * 0: no small factor (possible prime, more tests needed)
2168 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002169 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002170 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002171 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002172static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002173{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002174 int ret = 0;
2175 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002176 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002177
Paul Bakker5121ce52009-01-03 21:22:43 +00002178 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002179 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002180
2181 for( i = 0; small_prime[i] > 0; i++ )
2182 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002183 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002184 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002185
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002186 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002187
2188 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002189 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002190 }
2191
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002192cleanup:
2193 return( ret );
2194}
2195
2196/*
2197 * Miller-Rabin pseudo-primality test (HAC 4.24)
2198 */
Janos Follath72d555d2018-09-03 14:45:23 +01002199static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002200 int (*f_rng)(void *, unsigned char *, size_t),
2201 void *p_rng )
2202{
Pascal Junodb99183d2015-03-11 16:49:45 +01002203 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002204 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002205 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002206
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002207 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2208 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002209
Paul Bakker5121ce52009-01-03 21:22:43 +00002210 /*
2211 * W = |X| - 1
2212 * R = W >> lsb( W )
2213 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002214 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2215 s = mbedtls_mpi_lsb( &W );
2216 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2217 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002218
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002219 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002220
Janos Follath72d555d2018-09-03 14:45:23 +01002221 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002222 {
2223 /*
2224 * pick a random A, 1 < A < |X| - 1
2225 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002226 count = 0;
2227 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002228 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002229
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002230 j = mbedtls_mpi_bitlen( &A );
2231 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002232 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002233 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002234 }
2235
2236 if (count++ > 30) {
Jens Wiklanderb2aa9382019-01-17 13:30:57 +01002237 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2238 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002239 }
2240
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002241 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2242 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002243
2244 /*
2245 * A = A^R mod |X|
2246 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002247 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002248
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002249 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2250 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002251 continue;
2252
2253 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002254 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002255 {
2256 /*
2257 * A = A * A mod |X|
2258 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002259 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2260 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002261
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002262 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002263 break;
2264
2265 j++;
2266 }
2267
2268 /*
2269 * not prime if A != |X| - 1 or A == 1
2270 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002271 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2272 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002273 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002274 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002275 break;
2276 }
2277 }
2278
2279cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002280 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2281 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002282
2283 return( ret );
2284}
2285
2286/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002287 * Pseudo-primality test: small factors, then Miller-Rabin
2288 */
Darryl Green94759f62018-10-16 15:09:19 +01002289static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002290 int (*f_rng)(void *, unsigned char *, size_t),
2291 void *p_rng )
2292{
2293 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002294 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002295
2296 XX.s = 1;
2297 XX.n = X->n;
2298 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002299
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002300 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2301 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2302 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002303
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002304 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002305 return( 0 );
2306
2307 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2308 {
2309 if( ret == 1 )
2310 return( 0 );
2311
2312 return( ret );
2313 }
2314
Janos Follath72d555d2018-09-03 14:45:23 +01002315 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2316}
2317
2318/*
2319 * Pseudo-primality test, error probability 2^-80
2320 */
2321int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2322 int (*f_rng)(void *, unsigned char *, size_t),
2323 void *p_rng )
2324{
2325 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002326}
2327
2328/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002329 * Prime number generation
2330 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002331int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002332 int (*f_rng)(void *, unsigned char *, size_t),
2333 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002334{
Paul Bakker23986e52011-04-24 08:57:21 +00002335 int ret;
2336 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002337 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 mbedtls_mpi_uint r;
2339 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2342 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002344 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002345
2346 n = BITS_TO_LIMBS( nbits );
2347
Janos Follath72d555d2018-09-03 14:45:23 +01002348 /*
2349 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2350 */
2351 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2352 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2353 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2354
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002355 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002356
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002357 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002358 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002359
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002360 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002361
2362 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002363
2364 if( dh_flag == 0 )
2365 {
Janos Follath72d555d2018-09-03 14:45:23 +01002366 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002367 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002368 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002369 goto cleanup;
2370
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002371 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002372 }
2373 }
2374 else
2375 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002376 /*
2377 * An necessary condition for Y and X = 2Y + 1 to be prime
2378 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2379 * Make sure it is satisfied, while keeping X = 3 mod 4
2380 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002381
2382 X->p[0] |= 2;
2383
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002384 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002385 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002386 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002387 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002388 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002389
2390 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002391 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2392 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002393
2394 while( 1 )
2395 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002396 /*
2397 * First, check small factors for X and Y
2398 * before doing Miller-Rabin on any of them
2399 */
2400 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2401 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002402 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2403 == 0 &&
2404 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2405 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002406 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002407 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002408 }
2409
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002410 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002411 goto cleanup;
2412
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002413 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002414 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002415 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2416 * so up Y by 6 and X by 12.
2417 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002418 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2419 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002420 }
2421 }
2422
2423cleanup:
2424
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002425 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002426
2427 return( ret );
2428}
2429
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002430#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002431
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002432#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002433
Paul Bakker23986e52011-04-24 08:57:21 +00002434#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002435
2436static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2437{
2438 { 693, 609, 21 },
2439 { 1764, 868, 28 },
2440 { 768454923, 542167814, 1 }
2441};
2442
Paul Bakker5121ce52009-01-03 21:22:43 +00002443/*
2444 * Checkup routine
2445 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002446int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002447{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002448 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002449 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002451 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2452 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002453
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002454 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002455 "EFE021C2645FD1DC586E69184AF4A31E" \
2456 "D5F53E93B5F123FA41680867BA110131" \
2457 "944FE7952E2517337780CB0DB80E61AA" \
2458 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002460 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002461 "B2E7EFD37075B9F03FF989C7C5051C20" \
2462 "34D2A323810251127E7BF8625A4F49A5" \
2463 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2464 "5B5C25763222FEFCCFC38B832366C29E" ) );
2465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002466 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002467 "0066A198186C18C10B2F5ED9B522752A" \
2468 "9830B69916E535C8F047518A889A43A5" \
2469 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002471 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002474 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2475 "9E857EA95A03512E2BAE7391688D264A" \
2476 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2477 "8001B72E848A38CAE1C65F78E56ABDEF" \
2478 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2479 "ECF677152EF804370C1A305CAF3B5BF1" \
2480 "30879B56C61DE584A0F53A2447A51E" ) );
2481
2482 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002483 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002484
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002485 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002486 {
2487 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002488 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002489
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002490 ret = 1;
2491 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002492 }
2493
2494 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002495 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002497 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002499 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002500 "256567336059E52CAE22925474705F39A94" ) );
2501
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002502 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002503 "6613F26162223DF488E9CD48CC132C7A" \
2504 "0AC93C701B001B092E4E5B9F73BCD27B" \
2505 "9EE50D0657C77F374E903CDFA4C642" ) );
2506
2507 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002508 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002509
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002510 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2511 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002512 {
2513 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002514 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002515
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002516 ret = 1;
2517 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002518 }
2519
2520 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002521 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002522
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002523 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002525 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002526 "36E139AEA55215609D2816998ED020BB" \
2527 "BD96C37890F65171D948E9BC7CBAA4D9" \
2528 "325D24D6A3C12710F10A09FA08AB87" ) );
2529
2530 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002531 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002532
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002533 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002534 {
2535 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002536 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002537
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002538 ret = 1;
2539 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002540 }
2541
2542 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002543 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002544
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002545 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002546
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002547 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002548 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2549 "C3DBA76456363A10869622EAC2DD84EC" \
2550 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2551
2552 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002553 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002555 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002556 {
2557 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002558 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002559
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002560 ret = 1;
2561 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002562 }
2563
2564 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002565 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002566
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002567 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002568 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002569
Paul Bakker66d5d072014-06-17 16:39:18 +02002570 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002571 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002572 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2573 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002574
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002575 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002576
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002577 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002578 {
2579 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002580 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002581
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002582 ret = 1;
2583 goto cleanup;
2584 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002585 }
2586
2587 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002588 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002589
Paul Bakker5121ce52009-01-03 21:22:43 +00002590cleanup:
2591
2592 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002593 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002594
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002595 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2596 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002597
2598 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002599 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002600
2601 return( ret );
2602}
2603
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002604#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002605
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002606#endif /* MBEDTLS_BIGNUM_C */