blob: f07f746d4630bb8474ef196a1f2045a3cbabab50 [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
Janos Follath58239612019-10-29 15:08:46 +0000954 return (unsigned) ret;
Janos Follathe0187b92019-09-05 14:47:19 +0100955}
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 Follatha2b9a962019-10-28 12:23:18 +0000964 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath8ec2a952019-10-28 12:31:34 +0000965 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathe0187b92019-09-05 14:47:19 +0100966
967 if( X->n != Y->n )
968 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
969
970 /*
Janos Follath51ed14e2019-10-28 12:12:15 +0000971 * Set sign_N to 1 if N >= 0, 0 if N < 0.
972 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathe0187b92019-09-05 14:47:19 +0100973 */
Janos Follath8ec2a952019-10-28 12:31:34 +0000974 X_is_negative = ( X->s & 2 ) >> 1;
975 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follathc3b376e2019-10-11 14:21:53 +0100976
977 /*
978 * If the signs are different, then the positive operand is the bigger.
Janos Follath8ec2a952019-10-28 12:31:34 +0000979 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
980 * is false if X is positive (X_is_negative == 0).
Janos Follathc3b376e2019-10-11 14:21:53 +0100981 */
Janos Follath8ec2a952019-10-28 12:31:34 +0000982 cond = ( X_is_negative ^ Y_is_negative );
983 *ret = cond & X_is_negative;
Janos Follathc3b376e2019-10-11 14:21:53 +0100984
985 /*
Janos Follatha2b9a962019-10-28 12:23:18 +0000986 * This is a constant-time function. We might have the result, but we still
Janos Follathc3b376e2019-10-11 14:21:53 +0100987 * need to go through the loop. Record if we have the result already.
988 */
Janos Follathe0187b92019-09-05 14:47:19 +0100989 done = cond;
990
991 for( i = X->n; i > 0; i-- )
992 {
993 /*
Janos Follathc3b376e2019-10-11 14:21:53 +0100994 * If Y->p[i - 1] < X->p[i - 1] and both X and Y are negative, then
995 * X < Y.
996 *
997 * Again even if we can make a decision, we just mark the result and
998 * the fact that we are done and continue looping.
Janos Follathe0187b92019-09-05 14:47:19 +0100999 */
Janos Follath8ec2a952019-10-28 12:31:34 +00001000 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] ) & X_is_negative;
Janos Follathc3b376e2019-10-11 14:21:53 +01001001 *ret |= cond & ( 1 - done );
Janos Follathcff9e6e2019-10-28 12:37:21 +00001002 done |= cond;
Janos Follathe0187b92019-09-05 14:47:19 +01001003
1004 /*
Janos Follathc3b376e2019-10-11 14:21:53 +01001005 * If X->p[i - 1] < Y->p[i - 1] and both X and Y are positive, then
1006 * X < Y.
1007 *
1008 * Again even if we can make a decision, we just mark the result and
1009 * the fact that we are done and continue looping.
Janos Follathe0187b92019-09-05 14:47:19 +01001010 */
Janos Follath8ec2a952019-10-28 12:31:34 +00001011 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] )
1012 & ( 1 - X_is_negative );
Janos Follathc3b376e2019-10-11 14:21:53 +01001013 *ret |= cond & ( 1 - done );
Janos Follathcff9e6e2019-10-28 12:37:21 +00001014 done |= cond;
Janos Follathe0187b92019-09-05 14:47:19 +01001015 }
1016
1017 return( 0 );
1018}
1019
Paul Bakker5121ce52009-01-03 21:22:43 +00001020/*
1021 * Compare signed values
1022 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001023int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001024{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001025 mbedtls_mpi Y;
1026 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001027
1028 *p = ( z < 0 ) ? -z : z;
1029 Y.s = ( z < 0 ) ? -1 : 1;
1030 Y.n = 1;
1031 Y.p = p;
1032
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001033 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001034}
1035
1036/*
1037 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1038 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001039int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001040{
Paul Bakker23986e52011-04-24 08:57:21 +00001041 int ret;
1042 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001043 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +00001044
1045 if( X == B )
1046 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001047 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001048 }
1049
1050 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001051 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001052
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001053 /*
1054 * X should always be positive as a result of unsigned additions.
1055 */
1056 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001057
Paul Bakker23986e52011-04-24 08:57:21 +00001058 for( j = B->n; j > 0; j-- )
1059 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001060 break;
1061
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001062 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001063
1064 o = B->p; p = X->p; c = 0;
1065
Janos Follath6c922682015-10-30 17:43:11 +01001066 /*
1067 * tmp is used because it might happen that p == o
1068 */
Paul Bakker23986e52011-04-24 08:57:21 +00001069 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001070 {
Janos Follath6c922682015-10-30 17:43:11 +01001071 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001072 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001073 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001074 }
1075
1076 while( c != 0 )
1077 {
1078 if( i >= X->n )
1079 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001080 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001081 p = X->p + i;
1082 }
1083
Paul Bakker2d319fd2012-09-16 21:34:26 +00001084 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001085 }
1086
1087cleanup:
1088
1089 return( ret );
1090}
1091
1092/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001093 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001094 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001095static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001096{
Paul Bakker23986e52011-04-24 08:57:21 +00001097 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001098 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001099
1100 for( i = c = 0; i < n; i++, s++, d++ )
1101 {
1102 z = ( *d < c ); *d -= c;
1103 c = ( *d < *s ) + z; *d -= *s;
1104 }
1105
1106 while( c != 0 )
1107 {
1108 z = ( *d < c ); *d -= c;
1109 c = z; i++; d++;
1110 }
1111}
1112
1113/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001114 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001115 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001116int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001117{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001118 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001119 int ret;
1120 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001121
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001122 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1123 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001125 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001126
1127 if( X == B )
1128 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001129 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001130 B = &TB;
1131 }
1132
1133 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001134 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001135
Paul Bakker1ef7a532009-06-20 10:50:55 +00001136 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001137 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001138 */
1139 X->s = 1;
1140
Paul Bakker5121ce52009-01-03 21:22:43 +00001141 ret = 0;
1142
Paul Bakker23986e52011-04-24 08:57:21 +00001143 for( n = B->n; n > 0; n-- )
1144 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001145 break;
1146
Paul Bakker23986e52011-04-24 08:57:21 +00001147 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001148
1149cleanup:
1150
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001151 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001152
1153 return( ret );
1154}
1155
1156/*
1157 * Signed addition: X = A + B
1158 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001159int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001160{
1161 int ret, s = A->s;
1162
1163 if( A->s * B->s < 0 )
1164 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001165 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001166 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001167 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001168 X->s = s;
1169 }
1170 else
1171 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001172 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001173 X->s = -s;
1174 }
1175 }
1176 else
1177 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001178 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001179 X->s = s;
1180 }
1181
1182cleanup:
1183
1184 return( ret );
1185}
1186
1187/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001188 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001189 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001190int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001191{
1192 int ret, s = A->s;
1193
1194 if( A->s * B->s > 0 )
1195 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001196 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001197 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001198 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001199 X->s = s;
1200 }
1201 else
1202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001203 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001204 X->s = -s;
1205 }
1206 }
1207 else
1208 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001209 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001210 X->s = s;
1211 }
1212
1213cleanup:
1214
1215 return( ret );
1216}
1217
1218/*
1219 * Signed addition: X = A + b
1220 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001221int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001222{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001223 mbedtls_mpi _B;
1224 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001225
1226 p[0] = ( b < 0 ) ? -b : b;
1227 _B.s = ( b < 0 ) ? -1 : 1;
1228 _B.n = 1;
1229 _B.p = p;
1230
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001231 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001232}
1233
1234/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001235 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001236 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001237int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001238{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001239 mbedtls_mpi _B;
1240 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001241
1242 p[0] = ( b < 0 ) ? -b : b;
1243 _B.s = ( b < 0 ) ? -1 : 1;
1244 _B.n = 1;
1245 _B.p = p;
1246
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001247 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001248}
1249
1250/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001251 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001252 */
1253static
1254#if defined(__APPLE__) && defined(__arm__)
1255/*
1256 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1257 * appears to need this to prevent bad ARM code generation at -O3.
1258 */
1259__attribute__ ((noinline))
1260#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001261void 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 +00001262{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001263 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001264
1265#if defined(MULADDC_HUIT)
1266 for( ; i >= 8; i -= 8 )
1267 {
1268 MULADDC_INIT
1269 MULADDC_HUIT
1270 MULADDC_STOP
1271 }
1272
1273 for( ; i > 0; i-- )
1274 {
1275 MULADDC_INIT
1276 MULADDC_CORE
1277 MULADDC_STOP
1278 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001279#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001280 for( ; i >= 16; i -= 16 )
1281 {
1282 MULADDC_INIT
1283 MULADDC_CORE MULADDC_CORE
1284 MULADDC_CORE MULADDC_CORE
1285 MULADDC_CORE MULADDC_CORE
1286 MULADDC_CORE MULADDC_CORE
1287
1288 MULADDC_CORE MULADDC_CORE
1289 MULADDC_CORE MULADDC_CORE
1290 MULADDC_CORE MULADDC_CORE
1291 MULADDC_CORE MULADDC_CORE
1292 MULADDC_STOP
1293 }
1294
1295 for( ; i >= 8; i -= 8 )
1296 {
1297 MULADDC_INIT
1298 MULADDC_CORE MULADDC_CORE
1299 MULADDC_CORE MULADDC_CORE
1300
1301 MULADDC_CORE MULADDC_CORE
1302 MULADDC_CORE MULADDC_CORE
1303 MULADDC_STOP
1304 }
1305
1306 for( ; i > 0; i-- )
1307 {
1308 MULADDC_INIT
1309 MULADDC_CORE
1310 MULADDC_STOP
1311 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001312#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001313
1314 t++;
1315
1316 do {
1317 *d += c; c = ( *d < c ); d++;
1318 }
1319 while( c != 0 );
1320}
1321
1322/*
1323 * Baseline multiplication: X = A * B (HAC 14.12)
1324 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001325int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001326{
Paul Bakker23986e52011-04-24 08:57:21 +00001327 int ret;
1328 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001329 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001330
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001331 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001333 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1334 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001335
Paul Bakker23986e52011-04-24 08:57:21 +00001336 for( i = A->n; i > 0; i-- )
1337 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001338 break;
1339
Paul Bakker23986e52011-04-24 08:57:21 +00001340 for( j = B->n; j > 0; j-- )
1341 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001342 break;
1343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001344 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1345 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001346
Paul Bakker23986e52011-04-24 08:57:21 +00001347 for( i++; j > 0; j-- )
1348 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001349
1350 X->s = A->s * B->s;
1351
1352cleanup:
1353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001354 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001355
1356 return( ret );
1357}
1358
1359/*
1360 * Baseline multiplication: X = A * b
1361 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001362int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001363{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001364 mbedtls_mpi _B;
1365 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001366
1367 _B.s = 1;
1368 _B.n = 1;
1369 _B.p = p;
1370 p[0] = b;
1371
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001373}
1374
1375/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001376 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1377 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001378 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001379static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1380 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001381{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001382#if defined(MBEDTLS_HAVE_UDBL)
1383 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001384#else
Simon Butcher9803d072016-01-03 00:24:34 +00001385 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1386 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001387 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1388 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001389 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001390#endif
1391
Simon Butcher15b15d12015-11-26 19:35:03 +00001392 /*
1393 * Check for overflow
1394 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001395 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001396 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001397 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001398
Simon Butcherf5ba0452015-12-27 23:01:55 +00001399 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001400 }
1401
1402#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001403 dividend = (mbedtls_t_udbl) u1 << biL;
1404 dividend |= (mbedtls_t_udbl) u0;
1405 quotient = dividend / d;
1406 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1407 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1408
1409 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001410 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001411
1412 return (mbedtls_mpi_uint) quotient;
1413#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001414
1415 /*
1416 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1417 * Vol. 2 - Seminumerical Algorithms, Knuth
1418 */
1419
1420 /*
1421 * Normalize the divisor, d, and dividend, u0, u1
1422 */
1423 s = mbedtls_clz( d );
1424 d = d << s;
1425
1426 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001427 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001428 u0 = u0 << s;
1429
1430 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001431 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001432
1433 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001434 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001435
1436 /*
1437 * Find the first quotient and remainder
1438 */
1439 q1 = u1 / d1;
1440 r0 = u1 - d1 * q1;
1441
1442 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1443 {
1444 q1 -= 1;
1445 r0 += d1;
1446
1447 if ( r0 >= radix ) break;
1448 }
1449
Simon Butcherf5ba0452015-12-27 23:01:55 +00001450 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001451 q0 = rAX / d1;
1452 r0 = rAX - q0 * d1;
1453
1454 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1455 {
1456 q0 -= 1;
1457 r0 += d1;
1458
1459 if ( r0 >= radix ) break;
1460 }
1461
1462 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001463 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001464
1465 quotient = q1 * radix + q0;
1466
1467 return quotient;
1468#endif
1469}
1470
1471/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001472 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001473 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001474int 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 +00001475{
Paul Bakker23986e52011-04-24 08:57:21 +00001476 int ret;
1477 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001478 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001479
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001480 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1481 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001483 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1484 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001485
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001486 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001487 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001488 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1489 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001490 return( 0 );
1491 }
1492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001493 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1494 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001495 X.s = Y.s = 1;
1496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001497 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1498 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1499 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1500 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001501
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001502 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001503 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001504 {
1505 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1507 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001508 }
1509 else k = 0;
1510
1511 n = X.n - 1;
1512 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001513 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001514
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001515 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001516 {
1517 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001518 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001519 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001520 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001521
1522 for( i = n; i > t ; i-- )
1523 {
1524 if( X.p[i] >= Y.p[t] )
1525 Z.p[i - t - 1] = ~0;
1526 else
1527 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001528 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1529 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001530 }
1531
1532 Z.p[i - t - 1]++;
1533 do
1534 {
1535 Z.p[i - t - 1]--;
1536
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001537 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001538 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001539 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001540 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001541
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001542 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001543 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1544 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001545 T2.p[2] = X.p[i];
1546 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001547 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001548
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001549 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1550 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1551 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001552
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001553 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001554 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001555 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1556 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1557 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001558 Z.p[i - t - 1]--;
1559 }
1560 }
1561
1562 if( Q != NULL )
1563 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001564 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001565 Q->s = A->s * B->s;
1566 }
1567
1568 if( R != NULL )
1569 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001570 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001571 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001572 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001573
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001574 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001575 R->s = 1;
1576 }
1577
1578cleanup:
1579
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001580 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1581 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001582
1583 return( ret );
1584}
1585
1586/*
1587 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001588 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001589int 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 +00001590{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001591 mbedtls_mpi _B;
1592 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001593
1594 p[0] = ( b < 0 ) ? -b : b;
1595 _B.s = ( b < 0 ) ? -1 : 1;
1596 _B.n = 1;
1597 _B.p = p;
1598
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001599 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001600}
1601
1602/*
1603 * Modulo: R = A mod B
1604 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001605int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001606{
1607 int ret;
1608
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001609 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1610 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001612 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001613
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001614 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1615 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001617 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1618 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001619
1620cleanup:
1621
1622 return( ret );
1623}
1624
1625/*
1626 * Modulo: r = A mod b
1627 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001628int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001629{
Paul Bakker23986e52011-04-24 08:57:21 +00001630 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001631 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001632
1633 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001634 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001635
1636 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001637 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001638
1639 /*
1640 * handle trivial cases
1641 */
1642 if( b == 1 )
1643 {
1644 *r = 0;
1645 return( 0 );
1646 }
1647
1648 if( b == 2 )
1649 {
1650 *r = A->p[0] & 1;
1651 return( 0 );
1652 }
1653
1654 /*
1655 * general case
1656 */
Paul Bakker23986e52011-04-24 08:57:21 +00001657 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001658 {
Paul Bakker23986e52011-04-24 08:57:21 +00001659 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001660 y = ( y << biH ) | ( x >> biH );
1661 z = y / b;
1662 y -= z * b;
1663
1664 x <<= biH;
1665 y = ( y << biH ) | ( x >> biH );
1666 z = y / b;
1667 y -= z * b;
1668 }
1669
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001670 /*
1671 * If A is negative, then the current y represents a negative value.
1672 * Flipping it to the positive side.
1673 */
1674 if( A->s < 0 && y != 0 )
1675 y = b - y;
1676
Paul Bakker5121ce52009-01-03 21:22:43 +00001677 *r = y;
1678
1679 return( 0 );
1680}
1681
1682/*
1683 * Fast Montgomery initialization (thanks to Tom St Denis)
1684 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001685static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001686{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001687 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001688 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001689
1690 x = m0;
1691 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001692
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001693 for( i = biL; i >= 8; i /= 2 )
1694 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001695
1696 *mm = ~x + 1;
1697}
1698
1699/*
1700 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1701 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001702static 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 +02001703 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001704{
Paul Bakker23986e52011-04-24 08:57:21 +00001705 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001706 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001707
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001708 if( T->n < N->n + 1 || T->p == NULL )
1709 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1710
Paul Bakker5121ce52009-01-03 21:22:43 +00001711 memset( T->p, 0, T->n * ciL );
1712
1713 d = T->p;
1714 n = N->n;
1715 m = ( B->n < n ) ? B->n : n;
1716
1717 for( i = 0; i < n; i++ )
1718 {
1719 /*
1720 * T = (T + u0*B + u1*N) / 2^biL
1721 */
1722 u0 = A->p[i];
1723 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1724
1725 mpi_mul_hlp( m, B->p, d, u0 );
1726 mpi_mul_hlp( n, N->p, d, u1 );
1727
1728 *d++ = u0; d[n + 1] = 0;
1729 }
1730
Paul Bakker66d5d072014-06-17 16:39:18 +02001731 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001732
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001733 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001734 mpi_sub_hlp( n, N->p, A->p );
1735 else
1736 /* prevent timing attacks */
1737 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001738
1739 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001740}
1741
1742/*
1743 * Montgomery reduction: A = A * R^-1 mod N
1744 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001745static 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 +00001746{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001747 mbedtls_mpi_uint z = 1;
1748 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001749
Paul Bakker8ddb6452013-02-27 14:56:33 +01001750 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001751 U.p = &z;
1752
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001753 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001754}
1755
1756/*
1757 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1758 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001759int 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 +00001760{
Paul Bakker23986e52011-04-24 08:57:21 +00001761 int ret;
1762 size_t wbits, wsize, one = 1;
1763 size_t i, j, nblimbs;
1764 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001765 mbedtls_mpi_uint ei, mm, state;
1766 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001767 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001768
Hanno Becker930ec7d2018-03-09 10:48:00 +00001769 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001770 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001771
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001772 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1773 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001774
1775 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001776 * Init temps and window size
1777 */
1778 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001779 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1780 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001781 memset( W, 0, sizeof( W ) );
1782
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001783 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001784
1785 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1786 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1787
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001788#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001789 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1790 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001791#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001792
Paul Bakker5121ce52009-01-03 21:22:43 +00001793 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001794 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1795 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1796 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001797
1798 /*
Paul Bakker50546922012-05-19 08:40:49 +00001799 * Compensate for negative A (and correct at the end)
1800 */
1801 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001802 if( neg )
1803 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001804 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001805 Apos.s = 1;
1806 A = &Apos;
1807 }
1808
1809 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001810 * If 1st call, pre-compute R^2 mod N
1811 */
1812 if( _RR == NULL || _RR->p == NULL )
1813 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001814 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1815 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1816 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001817
1818 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001819 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001820 }
1821 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001822 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001823
1824 /*
1825 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1826 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001827 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1828 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001829 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001831
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001832 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001833
1834 /*
1835 * X = R^2 * R^-1 mod N = R mod N
1836 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001837 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001838 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001839
1840 if( wsize > 1 )
1841 {
1842 /*
1843 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1844 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001845 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001847 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1848 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001849
1850 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001851 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001852
Paul Bakker5121ce52009-01-03 21:22:43 +00001853 /*
1854 * W[i] = W[i - 1] * W[1]
1855 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001856 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001857 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001858 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1859 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001860
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001861 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001862 }
1863 }
1864
1865 nblimbs = E->n;
1866 bufsize = 0;
1867 nbits = 0;
1868 wbits = 0;
1869 state = 0;
1870
1871 while( 1 )
1872 {
1873 if( bufsize == 0 )
1874 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001875 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001876 break;
1877
Paul Bakker0d7702c2013-10-29 16:18:35 +01001878 nblimbs--;
1879
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001881 }
1882
1883 bufsize--;
1884
1885 ei = (E->p[nblimbs] >> bufsize) & 1;
1886
1887 /*
1888 * skip leading 0s
1889 */
1890 if( ei == 0 && state == 0 )
1891 continue;
1892
1893 if( ei == 0 && state == 1 )
1894 {
1895 /*
1896 * out of window, square X
1897 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001898 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001899 continue;
1900 }
1901
1902 /*
1903 * add ei to current window
1904 */
1905 state = 2;
1906
1907 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001908 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001909
1910 if( nbits == wsize )
1911 {
1912 /*
1913 * X = X^wsize R^-1 mod N
1914 */
1915 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001916 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001917
1918 /*
1919 * X = X * W[wbits] R^-1 mod N
1920 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001921 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001922
1923 state--;
1924 nbits = 0;
1925 wbits = 0;
1926 }
1927 }
1928
1929 /*
1930 * process the remaining bits
1931 */
1932 for( i = 0; i < nbits; i++ )
1933 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001934 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001935
1936 wbits <<= 1;
1937
Paul Bakker66d5d072014-06-17 16:39:18 +02001938 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001939 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001940 }
1941
1942 /*
1943 * X = A^E * R * R^-1 mod N = A^E mod N
1944 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001945 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001946
Hanno Beckera4af1c42017-04-18 09:07:45 +01001947 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001948 {
1949 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001950 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001951 }
1952
Paul Bakker5121ce52009-01-03 21:22:43 +00001953cleanup:
1954
Paul Bakker66d5d072014-06-17 16:39:18 +02001955 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001956 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001957
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001958 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001959
Paul Bakker75a28602014-03-31 12:08:17 +02001960 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001961 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001962
1963 return( ret );
1964}
1965
Paul Bakker5121ce52009-01-03 21:22:43 +00001966/*
1967 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1968 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001969int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001970{
Paul Bakker23986e52011-04-24 08:57:21 +00001971 int ret;
1972 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001973 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001974
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001975 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001976
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001977 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1978 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001979
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001980 lz = mbedtls_mpi_lsb( &TA );
1981 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001982
Paul Bakker66d5d072014-06-17 16:39:18 +02001983 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001984 lz = lzt;
1985
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001986 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1987 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001988
Paul Bakker5121ce52009-01-03 21:22:43 +00001989 TA.s = TB.s = 1;
1990
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001991 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001992 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001993 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1994 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001995
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001996 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001997 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001998 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1999 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002000 }
2001 else
2002 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002003 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2004 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002005 }
2006 }
2007
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002008 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2009 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002010
2011cleanup:
2012
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002013 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002014
2015 return( ret );
2016}
2017
Paul Bakker33dc46b2014-04-30 16:11:39 +02002018/*
2019 * Fill X with size bytes of random.
2020 *
2021 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002022 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002023 * deterministic, eg for tests).
2024 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002025int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002026 int (*f_rng)(void *, unsigned char *, size_t),
2027 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002028{
Paul Bakker23986e52011-04-24 08:57:21 +00002029 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002030 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02002031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002032 if( size > MBEDTLS_MPI_MAX_SIZE )
2033 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002034
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002035 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2036 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002037
2038cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01002039 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002040 return( ret );
2041}
2042
Paul Bakker5121ce52009-01-03 21:22:43 +00002043/*
2044 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2045 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002047{
2048 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002050
Hanno Becker4bcb4912017-04-18 15:49:39 +01002051 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002053
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002054 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2055 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2056 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002057
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002061 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002062 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002063 goto cleanup;
2064 }
2065
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002066 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2067 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2068 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2069 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002070
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002071 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2072 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2073 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2074 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002075
2076 do
2077 {
2078 while( ( TU.p[0] & 1 ) == 0 )
2079 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002080 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002081
2082 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2083 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002084 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2085 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002086 }
2087
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002088 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2089 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002090 }
2091
2092 while( ( TV.p[0] & 1 ) == 0 )
2093 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002094 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002095
2096 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2097 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002098 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2099 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002100 }
2101
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002102 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2103 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002104 }
2105
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002106 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002107 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002108 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2109 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2110 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002111 }
2112 else
2113 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002114 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2115 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2116 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002117 }
2118 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002119 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002120
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002121 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2122 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002123
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002124 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2125 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002127 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002128
2129cleanup:
2130
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002131 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2132 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2133 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002134
2135 return( ret );
2136}
2137
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002138#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002139
Paul Bakker5121ce52009-01-03 21:22:43 +00002140static const int small_prime[] =
2141{
2142 3, 5, 7, 11, 13, 17, 19, 23,
2143 29, 31, 37, 41, 43, 47, 53, 59,
2144 61, 67, 71, 73, 79, 83, 89, 97,
2145 101, 103, 107, 109, 113, 127, 131, 137,
2146 139, 149, 151, 157, 163, 167, 173, 179,
2147 181, 191, 193, 197, 199, 211, 223, 227,
2148 229, 233, 239, 241, 251, 257, 263, 269,
2149 271, 277, 281, 283, 293, 307, 311, 313,
2150 317, 331, 337, 347, 349, 353, 359, 367,
2151 373, 379, 383, 389, 397, 401, 409, 419,
2152 421, 431, 433, 439, 443, 449, 457, 461,
2153 463, 467, 479, 487, 491, 499, 503, 509,
2154 521, 523, 541, 547, 557, 563, 569, 571,
2155 577, 587, 593, 599, 601, 607, 613, 617,
2156 619, 631, 641, 643, 647, 653, 659, 661,
2157 673, 677, 683, 691, 701, 709, 719, 727,
2158 733, 739, 743, 751, 757, 761, 769, 773,
2159 787, 797, 809, 811, 821, 823, 827, 829,
2160 839, 853, 857, 859, 863, 877, 881, 883,
2161 887, 907, 911, 919, 929, 937, 941, 947,
2162 953, 967, 971, 977, 983, 991, 997, -103
2163};
2164
2165/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002166 * Small divisors test (X must be positive)
2167 *
2168 * Return values:
2169 * 0: no small factor (possible prime, more tests needed)
2170 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002171 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002172 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002173 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002174static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002175{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002176 int ret = 0;
2177 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002178 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002179
Paul Bakker5121ce52009-01-03 21:22:43 +00002180 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002181 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002182
2183 for( i = 0; small_prime[i] > 0; i++ )
2184 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002185 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002186 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002187
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002189
2190 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002191 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002192 }
2193
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002194cleanup:
2195 return( ret );
2196}
2197
2198/*
2199 * Miller-Rabin pseudo-primality test (HAC 4.24)
2200 */
Janos Follath72d555d2018-09-03 14:45:23 +01002201static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002202 int (*f_rng)(void *, unsigned char *, size_t),
2203 void *p_rng )
2204{
Pascal Junodb99183d2015-03-11 16:49:45 +01002205 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002206 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002207 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002209 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2210 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002211
Paul Bakker5121ce52009-01-03 21:22:43 +00002212 /*
2213 * W = |X| - 1
2214 * R = W >> lsb( W )
2215 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002216 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2217 s = mbedtls_mpi_lsb( &W );
2218 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2219 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002220
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002221 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002222
Janos Follath72d555d2018-09-03 14:45:23 +01002223 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002224 {
2225 /*
2226 * pick a random A, 1 < A < |X| - 1
2227 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002228 count = 0;
2229 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002230 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002231
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002232 j = mbedtls_mpi_bitlen( &A );
2233 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002234 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002235 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002236 }
2237
2238 if (count++ > 30) {
Jens Wiklanderb2aa9382019-01-17 13:30:57 +01002239 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2240 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002241 }
2242
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002243 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2244 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002245
2246 /*
2247 * A = A^R mod |X|
2248 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002249 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002250
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002251 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2252 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002253 continue;
2254
2255 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002256 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002257 {
2258 /*
2259 * A = A * A mod |X|
2260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002261 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2262 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002265 break;
2266
2267 j++;
2268 }
2269
2270 /*
2271 * not prime if A != |X| - 1 or A == 1
2272 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002273 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2274 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002275 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002276 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002277 break;
2278 }
2279 }
2280
2281cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002282 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2283 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002284
2285 return( ret );
2286}
2287
2288/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002289 * Pseudo-primality test: small factors, then Miller-Rabin
2290 */
Darryl Green94759f62018-10-16 15:09:19 +01002291static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002292 int (*f_rng)(void *, unsigned char *, size_t),
2293 void *p_rng )
2294{
2295 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002296 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002297
2298 XX.s = 1;
2299 XX.n = X->n;
2300 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002301
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002302 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2303 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2304 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002305
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002306 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002307 return( 0 );
2308
2309 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2310 {
2311 if( ret == 1 )
2312 return( 0 );
2313
2314 return( ret );
2315 }
2316
Janos Follath72d555d2018-09-03 14:45:23 +01002317 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2318}
2319
2320/*
2321 * Pseudo-primality test, error probability 2^-80
2322 */
2323int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2324 int (*f_rng)(void *, unsigned char *, size_t),
2325 void *p_rng )
2326{
2327 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002328}
2329
2330/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002331 * Prime number generation
2332 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002333int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002334 int (*f_rng)(void *, unsigned char *, size_t),
2335 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002336{
Paul Bakker23986e52011-04-24 08:57:21 +00002337 int ret;
2338 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002339 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002340 mbedtls_mpi_uint r;
2341 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002343 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2344 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002346 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002347
2348 n = BITS_TO_LIMBS( nbits );
2349
Janos Follath72d555d2018-09-03 14:45:23 +01002350 /*
2351 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2352 */
2353 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2354 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2355 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2356
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002357 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002358
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002359 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002360 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002361
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002362 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002363
2364 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002365
2366 if( dh_flag == 0 )
2367 {
Janos Follath72d555d2018-09-03 14:45:23 +01002368 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002369 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002370 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002371 goto cleanup;
2372
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002373 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002374 }
2375 }
2376 else
2377 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002378 /*
2379 * An necessary condition for Y and X = 2Y + 1 to be prime
2380 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2381 * Make sure it is satisfied, while keeping X = 3 mod 4
2382 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002383
2384 X->p[0] |= 2;
2385
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002386 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002387 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002388 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002389 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002390 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002391
2392 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002393 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2394 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002395
2396 while( 1 )
2397 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002398 /*
2399 * First, check small factors for X and Y
2400 * before doing Miller-Rabin on any of them
2401 */
2402 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2403 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002404 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2405 == 0 &&
2406 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2407 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002408 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002409 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002410 }
2411
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002412 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002413 goto cleanup;
2414
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002415 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002416 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002417 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2418 * so up Y by 6 and X by 12.
2419 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002420 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2421 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002422 }
2423 }
2424
2425cleanup:
2426
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002427 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002428
2429 return( ret );
2430}
2431
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002432#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002435
Paul Bakker23986e52011-04-24 08:57:21 +00002436#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002437
2438static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2439{
2440 { 693, 609, 21 },
2441 { 1764, 868, 28 },
2442 { 768454923, 542167814, 1 }
2443};
2444
Paul Bakker5121ce52009-01-03 21:22:43 +00002445/*
2446 * Checkup routine
2447 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002448int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002449{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002450 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002451 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002453 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2454 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002456 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002457 "EFE021C2645FD1DC586E69184AF4A31E" \
2458 "D5F53E93B5F123FA41680867BA110131" \
2459 "944FE7952E2517337780CB0DB80E61AA" \
2460 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2461
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002462 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002463 "B2E7EFD37075B9F03FF989C7C5051C20" \
2464 "34D2A323810251127E7BF8625A4F49A5" \
2465 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2466 "5B5C25763222FEFCCFC38B832366C29E" ) );
2467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002468 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002469 "0066A198186C18C10B2F5ED9B522752A" \
2470 "9830B69916E535C8F047518A889A43A5" \
2471 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002474
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002476 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2477 "9E857EA95A03512E2BAE7391688D264A" \
2478 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2479 "8001B72E848A38CAE1C65F78E56ABDEF" \
2480 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2481 "ECF677152EF804370C1A305CAF3B5BF1" \
2482 "30879B56C61DE584A0F53A2447A51E" ) );
2483
2484 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002485 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002486
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002487 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002488 {
2489 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002490 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002491
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002492 ret = 1;
2493 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002494 }
2495
2496 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002497 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002499 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002500
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002501 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002502 "256567336059E52CAE22925474705F39A94" ) );
2503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002504 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002505 "6613F26162223DF488E9CD48CC132C7A" \
2506 "0AC93C701B001B092E4E5B9F73BCD27B" \
2507 "9EE50D0657C77F374E903CDFA4C642" ) );
2508
2509 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002510 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002511
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002512 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2513 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002514 {
2515 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002516 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002517
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002518 ret = 1;
2519 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002520 }
2521
2522 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002523 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002525 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002526
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002527 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002528 "36E139AEA55215609D2816998ED020BB" \
2529 "BD96C37890F65171D948E9BC7CBAA4D9" \
2530 "325D24D6A3C12710F10A09FA08AB87" ) );
2531
2532 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002533 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002534
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002535 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002536 {
2537 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002538 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002539
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002540 ret = 1;
2541 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002542 }
2543
2544 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002545 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002546
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002547 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002548
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002549 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002550 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2551 "C3DBA76456363A10869622EAC2DD84EC" \
2552 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2553
2554 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002555 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002556
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002557 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002558 {
2559 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002560 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002561
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002562 ret = 1;
2563 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002564 }
2565
2566 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002567 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002568
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002569 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002570 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002571
Paul Bakker66d5d072014-06-17 16:39:18 +02002572 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002573 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002574 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2575 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002576
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002577 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002578
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002579 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002580 {
2581 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002582 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002583
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002584 ret = 1;
2585 goto cleanup;
2586 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002587 }
2588
2589 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002590 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002591
Paul Bakker5121ce52009-01-03 21:22:43 +00002592cleanup:
2593
2594 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002595 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002596
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002597 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2598 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002599
2600 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002601 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002602
2603 return( ret );
2604}
2605
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002606#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002607
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002608#endif /* MBEDTLS_BIGNUM_C */