blob: fd9d5b8a89a99bde8a49f3c2642061ffc1076941 [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
Gilles Peskine2aeab872020-01-20 21:12:50 +0100193 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200194 {
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 Follathb4edac52019-11-05 12:24:52 +0000994 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
995 * X and Y are negative.
Janos Follathc3b376e2019-10-11 14:21:53 +0100996 *
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 Follathb4edac52019-11-05 12:24:52 +00001000 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1001 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathcff9e6e2019-10-28 12:37:21 +00001002 done |= cond;
Janos Follathe0187b92019-09-05 14:47:19 +01001003
1004 /*
Janos Follathb4edac52019-11-05 12:24:52 +00001005 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1006 * X and Y are positive.
Janos Follathc3b376e2019-10-11 14:21:53 +01001007 *
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 Follathb4edac52019-11-05 12:24:52 +00001011 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1012 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathcff9e6e2019-10-28 12:37:21 +00001013 done |= cond;
Janos Follathe0187b92019-09-05 14:47:19 +01001014 }
1015
1016 return( 0 );
1017}
1018
Paul Bakker5121ce52009-01-03 21:22:43 +00001019/*
1020 * Compare signed values
1021 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001022int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001023{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001024 mbedtls_mpi Y;
1025 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001026
1027 *p = ( z < 0 ) ? -z : z;
1028 Y.s = ( z < 0 ) ? -1 : 1;
1029 Y.n = 1;
1030 Y.p = p;
1031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001032 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001033}
1034
1035/*
1036 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1037 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001038int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001039{
Paul Bakker23986e52011-04-24 08:57:21 +00001040 int ret;
1041 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001042 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +00001043
1044 if( X == B )
1045 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001046 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001047 }
1048
1049 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001051
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001052 /*
1053 * X should always be positive as a result of unsigned additions.
1054 */
1055 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001056
Paul Bakker23986e52011-04-24 08:57:21 +00001057 for( j = B->n; j > 0; j-- )
1058 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001059 break;
1060
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001061 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001062
1063 o = B->p; p = X->p; c = 0;
1064
Janos Follath6c922682015-10-30 17:43:11 +01001065 /*
1066 * tmp is used because it might happen that p == o
1067 */
Paul Bakker23986e52011-04-24 08:57:21 +00001068 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001069 {
Janos Follath6c922682015-10-30 17:43:11 +01001070 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001071 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001072 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001073 }
1074
1075 while( c != 0 )
1076 {
1077 if( i >= X->n )
1078 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001079 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001080 p = X->p + i;
1081 }
1082
Paul Bakker2d319fd2012-09-16 21:34:26 +00001083 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001084 }
1085
1086cleanup:
1087
1088 return( ret );
1089}
1090
1091/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001092 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001093 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001094static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001095{
Paul Bakker23986e52011-04-24 08:57:21 +00001096 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001097 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001098
1099 for( i = c = 0; i < n; i++, s++, d++ )
1100 {
1101 z = ( *d < c ); *d -= c;
1102 c = ( *d < *s ) + z; *d -= *s;
1103 }
1104
1105 while( c != 0 )
1106 {
1107 z = ( *d < c ); *d -= c;
1108 c = z; i++; d++;
1109 }
1110}
1111
1112/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001113 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001114 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001116{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001117 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001118 int ret;
1119 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001120
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001121 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1122 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001123
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001124 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001125
1126 if( X == B )
1127 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001128 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001129 B = &TB;
1130 }
1131
1132 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001133 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001134
Paul Bakker1ef7a532009-06-20 10:50:55 +00001135 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001136 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001137 */
1138 X->s = 1;
1139
Paul Bakker5121ce52009-01-03 21:22:43 +00001140 ret = 0;
1141
Paul Bakker23986e52011-04-24 08:57:21 +00001142 for( n = B->n; n > 0; n-- )
1143 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001144 break;
1145
Paul Bakker23986e52011-04-24 08:57:21 +00001146 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001147
1148cleanup:
1149
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001150 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001151
1152 return( ret );
1153}
1154
1155/*
1156 * Signed addition: X = A + B
1157 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001158int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001159{
1160 int ret, s = A->s;
1161
1162 if( A->s * B->s < 0 )
1163 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001164 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001165 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001166 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001167 X->s = s;
1168 }
1169 else
1170 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001171 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001172 X->s = -s;
1173 }
1174 }
1175 else
1176 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001177 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001178 X->s = s;
1179 }
1180
1181cleanup:
1182
1183 return( ret );
1184}
1185
1186/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001187 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001188 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001189int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001190{
1191 int ret, s = A->s;
1192
1193 if( A->s * B->s > 0 )
1194 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001195 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001196 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001197 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001198 X->s = s;
1199 }
1200 else
1201 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001202 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001203 X->s = -s;
1204 }
1205 }
1206 else
1207 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001208 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001209 X->s = s;
1210 }
1211
1212cleanup:
1213
1214 return( ret );
1215}
1216
1217/*
1218 * Signed addition: X = A + b
1219 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001220int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001221{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001222 mbedtls_mpi _B;
1223 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001224
1225 p[0] = ( b < 0 ) ? -b : b;
1226 _B.s = ( b < 0 ) ? -1 : 1;
1227 _B.n = 1;
1228 _B.p = p;
1229
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001230 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001231}
1232
1233/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001234 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001235 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001236int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001237{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001238 mbedtls_mpi _B;
1239 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001240
1241 p[0] = ( b < 0 ) ? -b : b;
1242 _B.s = ( b < 0 ) ? -1 : 1;
1243 _B.n = 1;
1244 _B.p = p;
1245
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001246 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001247}
1248
1249/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001250 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001251 */
1252static
1253#if defined(__APPLE__) && defined(__arm__)
1254/*
1255 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1256 * appears to need this to prevent bad ARM code generation at -O3.
1257 */
1258__attribute__ ((noinline))
1259#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001260void 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 +00001261{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001262 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001263
1264#if defined(MULADDC_HUIT)
1265 for( ; i >= 8; i -= 8 )
1266 {
1267 MULADDC_INIT
1268 MULADDC_HUIT
1269 MULADDC_STOP
1270 }
1271
1272 for( ; i > 0; i-- )
1273 {
1274 MULADDC_INIT
1275 MULADDC_CORE
1276 MULADDC_STOP
1277 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001278#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001279 for( ; i >= 16; i -= 16 )
1280 {
1281 MULADDC_INIT
1282 MULADDC_CORE MULADDC_CORE
1283 MULADDC_CORE MULADDC_CORE
1284 MULADDC_CORE MULADDC_CORE
1285 MULADDC_CORE MULADDC_CORE
1286
1287 MULADDC_CORE MULADDC_CORE
1288 MULADDC_CORE MULADDC_CORE
1289 MULADDC_CORE MULADDC_CORE
1290 MULADDC_CORE MULADDC_CORE
1291 MULADDC_STOP
1292 }
1293
1294 for( ; i >= 8; i -= 8 )
1295 {
1296 MULADDC_INIT
1297 MULADDC_CORE MULADDC_CORE
1298 MULADDC_CORE MULADDC_CORE
1299
1300 MULADDC_CORE MULADDC_CORE
1301 MULADDC_CORE MULADDC_CORE
1302 MULADDC_STOP
1303 }
1304
1305 for( ; i > 0; i-- )
1306 {
1307 MULADDC_INIT
1308 MULADDC_CORE
1309 MULADDC_STOP
1310 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001311#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001312
1313 t++;
1314
1315 do {
1316 *d += c; c = ( *d < c ); d++;
1317 }
1318 while( c != 0 );
1319}
1320
1321/*
1322 * Baseline multiplication: X = A * B (HAC 14.12)
1323 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001324int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001325{
Paul Bakker23986e52011-04-24 08:57:21 +00001326 int ret;
1327 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001328 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001329
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001330 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1333 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001334
Paul Bakker23986e52011-04-24 08:57:21 +00001335 for( i = A->n; i > 0; i-- )
1336 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001337 break;
1338
Paul Bakker23986e52011-04-24 08:57:21 +00001339 for( j = B->n; j > 0; j-- )
1340 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001341 break;
1342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001343 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1344 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001345
Paul Bakker23986e52011-04-24 08:57:21 +00001346 for( i++; j > 0; j-- )
1347 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001348
1349 X->s = A->s * B->s;
1350
1351cleanup:
1352
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001353 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001354
1355 return( ret );
1356}
1357
1358/*
1359 * Baseline multiplication: X = A * b
1360 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001361int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001362{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001363 mbedtls_mpi _B;
1364 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001365
1366 _B.s = 1;
1367 _B.n = 1;
1368 _B.p = p;
1369 p[0] = b;
1370
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001371 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001372}
1373
1374/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001375 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1376 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001377 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001378static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1379 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001380{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001381#if defined(MBEDTLS_HAVE_UDBL)
1382 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001383#else
Simon Butcher9803d072016-01-03 00:24:34 +00001384 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1385 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001386 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1387 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001388 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001389#endif
1390
Simon Butcher15b15d12015-11-26 19:35:03 +00001391 /*
1392 * Check for overflow
1393 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001394 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001395 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001396 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001397
Simon Butcherf5ba0452015-12-27 23:01:55 +00001398 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001399 }
1400
1401#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001402 dividend = (mbedtls_t_udbl) u1 << biL;
1403 dividend |= (mbedtls_t_udbl) u0;
1404 quotient = dividend / d;
1405 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1406 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1407
1408 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001409 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001410
1411 return (mbedtls_mpi_uint) quotient;
1412#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001413
1414 /*
1415 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1416 * Vol. 2 - Seminumerical Algorithms, Knuth
1417 */
1418
1419 /*
1420 * Normalize the divisor, d, and dividend, u0, u1
1421 */
1422 s = mbedtls_clz( d );
1423 d = d << s;
1424
1425 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001426 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001427 u0 = u0 << s;
1428
1429 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001430 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001431
1432 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001433 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001434
1435 /*
1436 * Find the first quotient and remainder
1437 */
1438 q1 = u1 / d1;
1439 r0 = u1 - d1 * q1;
1440
1441 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1442 {
1443 q1 -= 1;
1444 r0 += d1;
1445
1446 if ( r0 >= radix ) break;
1447 }
1448
Simon Butcherf5ba0452015-12-27 23:01:55 +00001449 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001450 q0 = rAX / d1;
1451 r0 = rAX - q0 * d1;
1452
1453 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1454 {
1455 q0 -= 1;
1456 r0 += d1;
1457
1458 if ( r0 >= radix ) break;
1459 }
1460
1461 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001462 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001463
1464 quotient = q1 * radix + q0;
1465
1466 return quotient;
1467#endif
1468}
1469
1470/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001472 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001473int 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 +00001474{
Paul Bakker23986e52011-04-24 08:57:21 +00001475 int ret;
1476 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001477 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001478
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001479 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1480 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001482 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1483 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001484
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001485 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001486 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001487 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1488 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001489 return( 0 );
1490 }
1491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001492 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1493 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001494 X.s = Y.s = 1;
1495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001496 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1497 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1498 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1499 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001500
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001501 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001502 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001503 {
1504 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001505 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1506 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001507 }
1508 else k = 0;
1509
1510 n = X.n - 1;
1511 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001512 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001514 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001515 {
1516 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001517 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001518 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001519 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001520
1521 for( i = n; i > t ; i-- )
1522 {
1523 if( X.p[i] >= Y.p[t] )
1524 Z.p[i - t - 1] = ~0;
1525 else
1526 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001527 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1528 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001529 }
1530
1531 Z.p[i - t - 1]++;
1532 do
1533 {
1534 Z.p[i - t - 1]--;
1535
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001536 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001537 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001538 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001540
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001541 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001542 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1543 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001544 T2.p[2] = X.p[i];
1545 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001546 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001547
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001548 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1549 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1550 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001552 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001553 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001554 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1555 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1556 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001557 Z.p[i - t - 1]--;
1558 }
1559 }
1560
1561 if( Q != NULL )
1562 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001563 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001564 Q->s = A->s * B->s;
1565 }
1566
1567 if( R != NULL )
1568 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001569 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001570 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001571 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001572
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001573 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001574 R->s = 1;
1575 }
1576
1577cleanup:
1578
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001579 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1580 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001581
1582 return( ret );
1583}
1584
1585/*
1586 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001587 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001588int 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 +00001589{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001590 mbedtls_mpi _B;
1591 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001592
1593 p[0] = ( b < 0 ) ? -b : b;
1594 _B.s = ( b < 0 ) ? -1 : 1;
1595 _B.n = 1;
1596 _B.p = p;
1597
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001598 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001599}
1600
1601/*
1602 * Modulo: R = A mod B
1603 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001604int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001605{
1606 int ret;
1607
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001608 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1609 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001610
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001611 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001612
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001613 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1614 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001615
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001616 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1617 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001618
1619cleanup:
1620
1621 return( ret );
1622}
1623
1624/*
1625 * Modulo: r = A mod b
1626 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001627int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001628{
Paul Bakker23986e52011-04-24 08:57:21 +00001629 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001630 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001631
1632 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001633 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001634
1635 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001637
1638 /*
1639 * handle trivial cases
1640 */
1641 if( b == 1 )
1642 {
1643 *r = 0;
1644 return( 0 );
1645 }
1646
1647 if( b == 2 )
1648 {
1649 *r = A->p[0] & 1;
1650 return( 0 );
1651 }
1652
1653 /*
1654 * general case
1655 */
Paul Bakker23986e52011-04-24 08:57:21 +00001656 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001657 {
Paul Bakker23986e52011-04-24 08:57:21 +00001658 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001659 y = ( y << biH ) | ( x >> biH );
1660 z = y / b;
1661 y -= z * b;
1662
1663 x <<= biH;
1664 y = ( y << biH ) | ( x >> biH );
1665 z = y / b;
1666 y -= z * b;
1667 }
1668
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001669 /*
1670 * If A is negative, then the current y represents a negative value.
1671 * Flipping it to the positive side.
1672 */
1673 if( A->s < 0 && y != 0 )
1674 y = b - y;
1675
Paul Bakker5121ce52009-01-03 21:22:43 +00001676 *r = y;
1677
1678 return( 0 );
1679}
1680
1681/*
1682 * Fast Montgomery initialization (thanks to Tom St Denis)
1683 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001684static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001685{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001686 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001687 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001688
1689 x = m0;
1690 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001691
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001692 for( i = biL; i >= 8; i /= 2 )
1693 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001694
1695 *mm = ~x + 1;
1696}
1697
1698/*
1699 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1700 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001701static 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 +02001702 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001703{
Paul Bakker23986e52011-04-24 08:57:21 +00001704 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001705 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001706
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001707 if( T->n < N->n + 1 || T->p == NULL )
1708 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1709
Paul Bakker5121ce52009-01-03 21:22:43 +00001710 memset( T->p, 0, T->n * ciL );
1711
1712 d = T->p;
1713 n = N->n;
1714 m = ( B->n < n ) ? B->n : n;
1715
1716 for( i = 0; i < n; i++ )
1717 {
1718 /*
1719 * T = (T + u0*B + u1*N) / 2^biL
1720 */
1721 u0 = A->p[i];
1722 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1723
1724 mpi_mul_hlp( m, B->p, d, u0 );
1725 mpi_mul_hlp( n, N->p, d, u1 );
1726
1727 *d++ = u0; d[n + 1] = 0;
1728 }
1729
Paul Bakker66d5d072014-06-17 16:39:18 +02001730 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001731
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001732 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001733 mpi_sub_hlp( n, N->p, A->p );
1734 else
1735 /* prevent timing attacks */
1736 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001737
1738 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001739}
1740
1741/*
1742 * Montgomery reduction: A = A * R^-1 mod N
1743 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001744static 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 +00001745{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001746 mbedtls_mpi_uint z = 1;
1747 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001748
Paul Bakker8ddb6452013-02-27 14:56:33 +01001749 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001750 U.p = &z;
1751
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001752 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001753}
1754
1755/*
1756 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1757 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001758int 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 +00001759{
Paul Bakker23986e52011-04-24 08:57:21 +00001760 int ret;
1761 size_t wbits, wsize, one = 1;
1762 size_t i, j, nblimbs;
1763 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001764 mbedtls_mpi_uint ei, mm, state;
1765 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001766 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001767
Hanno Becker930ec7d2018-03-09 10:48:00 +00001768 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001769 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001770
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001771 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1772 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001773
1774 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001775 * Init temps and window size
1776 */
1777 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001778 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1779 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001780 memset( W, 0, sizeof( W ) );
1781
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001782 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001783
1784 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1785 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1786
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001787#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001788 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1789 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001790#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001791
Paul Bakker5121ce52009-01-03 21:22:43 +00001792 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001793 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1794 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1795 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001796
1797 /*
Paul Bakker50546922012-05-19 08:40:49 +00001798 * Compensate for negative A (and correct at the end)
1799 */
1800 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001801 if( neg )
1802 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001803 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001804 Apos.s = 1;
1805 A = &Apos;
1806 }
1807
1808 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001809 * If 1st call, pre-compute R^2 mod N
1810 */
1811 if( _RR == NULL || _RR->p == NULL )
1812 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001813 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1814 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1815 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001816
1817 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001818 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001819 }
1820 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001821 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001822
1823 /*
1824 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1825 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001826 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1827 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001828 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001829 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001830
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001831 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001832
1833 /*
1834 * X = R^2 * R^-1 mod N = R mod N
1835 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001836 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001837 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001838
1839 if( wsize > 1 )
1840 {
1841 /*
1842 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1843 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001844 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001845
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001846 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1847 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001848
1849 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001850 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001851
Paul Bakker5121ce52009-01-03 21:22:43 +00001852 /*
1853 * W[i] = W[i - 1] * W[1]
1854 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001855 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001856 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001857 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1858 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001859
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001860 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001861 }
1862 }
1863
1864 nblimbs = E->n;
1865 bufsize = 0;
1866 nbits = 0;
1867 wbits = 0;
1868 state = 0;
1869
1870 while( 1 )
1871 {
1872 if( bufsize == 0 )
1873 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001874 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001875 break;
1876
Paul Bakker0d7702c2013-10-29 16:18:35 +01001877 nblimbs--;
1878
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001880 }
1881
1882 bufsize--;
1883
1884 ei = (E->p[nblimbs] >> bufsize) & 1;
1885
1886 /*
1887 * skip leading 0s
1888 */
1889 if( ei == 0 && state == 0 )
1890 continue;
1891
1892 if( ei == 0 && state == 1 )
1893 {
1894 /*
1895 * out of window, square X
1896 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001897 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001898 continue;
1899 }
1900
1901 /*
1902 * add ei to current window
1903 */
1904 state = 2;
1905
1906 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001907 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001908
1909 if( nbits == wsize )
1910 {
1911 /*
1912 * X = X^wsize R^-1 mod N
1913 */
1914 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001915 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001916
1917 /*
1918 * X = X * W[wbits] R^-1 mod N
1919 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001920 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001921
1922 state--;
1923 nbits = 0;
1924 wbits = 0;
1925 }
1926 }
1927
1928 /*
1929 * process the remaining bits
1930 */
1931 for( i = 0; i < nbits; i++ )
1932 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001933 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001934
1935 wbits <<= 1;
1936
Paul Bakker66d5d072014-06-17 16:39:18 +02001937 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001938 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001939 }
1940
1941 /*
1942 * X = A^E * R * R^-1 mod N = A^E mod N
1943 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001944 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
Hanno Beckera4af1c42017-04-18 09:07:45 +01001946 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001947 {
1948 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001949 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001950 }
1951
Paul Bakker5121ce52009-01-03 21:22:43 +00001952cleanup:
1953
Paul Bakker66d5d072014-06-17 16:39:18 +02001954 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001955 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001957 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001958
Paul Bakker75a28602014-03-31 12:08:17 +02001959 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001960 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001961
1962 return( ret );
1963}
1964
Paul Bakker5121ce52009-01-03 21:22:43 +00001965/*
1966 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1967 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001968int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001969{
Paul Bakker23986e52011-04-24 08:57:21 +00001970 int ret;
1971 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001972 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001973
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001974 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001975
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001976 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1977 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001978
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001979 lz = mbedtls_mpi_lsb( &TA );
1980 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001981
Paul Bakker66d5d072014-06-17 16:39:18 +02001982 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001983 lz = lzt;
1984
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001985 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1986 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001987
Paul Bakker5121ce52009-01-03 21:22:43 +00001988 TA.s = TB.s = 1;
1989
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001990 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001991 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001992 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1993 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001994
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001995 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001996 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001997 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1998 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001999 }
2000 else
2001 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002002 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2003 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002004 }
2005 }
2006
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002007 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2008 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002009
2010cleanup:
2011
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002012 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002013
2014 return( ret );
2015}
2016
Paul Bakker33dc46b2014-04-30 16:11:39 +02002017/*
2018 * Fill X with size bytes of random.
2019 *
2020 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002021 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002022 * deterministic, eg for tests).
2023 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002024int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002025 int (*f_rng)(void *, unsigned char *, size_t),
2026 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002027{
Paul Bakker23986e52011-04-24 08:57:21 +00002028 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02002030
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002031 if( size > MBEDTLS_MPI_MAX_SIZE )
2032 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2035 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002036
2037cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01002038 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002039 return( ret );
2040}
2041
Paul Bakker5121ce52009-01-03 21:22:43 +00002042/*
2043 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2044 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002045int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002046{
2047 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002048 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002049
Hanno Becker4bcb4912017-04-18 15:49:39 +01002050 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002051 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002052
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002053 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2054 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2055 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002056
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002057 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002058
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002059 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002060 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002061 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002062 goto cleanup;
2063 }
2064
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002065 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2066 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2067 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2068 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002069
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002070 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2071 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2072 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2073 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002074
2075 do
2076 {
2077 while( ( TU.p[0] & 1 ) == 0 )
2078 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002079 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002080
2081 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2082 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002083 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2084 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002085 }
2086
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002087 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2088 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002089 }
2090
2091 while( ( TV.p[0] & 1 ) == 0 )
2092 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002093 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002094
2095 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2096 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002097 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2098 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002099 }
2100
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002101 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2102 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002103 }
2104
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002105 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002106 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002107 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2108 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2109 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002110 }
2111 else
2112 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002113 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2114 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2115 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002116 }
2117 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002118 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002120 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2121 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002123 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2124 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002125
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002126 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002127
2128cleanup:
2129
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002130 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2131 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2132 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002133
2134 return( ret );
2135}
2136
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002137#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002138
Paul Bakker5121ce52009-01-03 21:22:43 +00002139static const int small_prime[] =
2140{
2141 3, 5, 7, 11, 13, 17, 19, 23,
2142 29, 31, 37, 41, 43, 47, 53, 59,
2143 61, 67, 71, 73, 79, 83, 89, 97,
2144 101, 103, 107, 109, 113, 127, 131, 137,
2145 139, 149, 151, 157, 163, 167, 173, 179,
2146 181, 191, 193, 197, 199, 211, 223, 227,
2147 229, 233, 239, 241, 251, 257, 263, 269,
2148 271, 277, 281, 283, 293, 307, 311, 313,
2149 317, 331, 337, 347, 349, 353, 359, 367,
2150 373, 379, 383, 389, 397, 401, 409, 419,
2151 421, 431, 433, 439, 443, 449, 457, 461,
2152 463, 467, 479, 487, 491, 499, 503, 509,
2153 521, 523, 541, 547, 557, 563, 569, 571,
2154 577, 587, 593, 599, 601, 607, 613, 617,
2155 619, 631, 641, 643, 647, 653, 659, 661,
2156 673, 677, 683, 691, 701, 709, 719, 727,
2157 733, 739, 743, 751, 757, 761, 769, 773,
2158 787, 797, 809, 811, 821, 823, 827, 829,
2159 839, 853, 857, 859, 863, 877, 881, 883,
2160 887, 907, 911, 919, 929, 937, 941, 947,
2161 953, 967, 971, 977, 983, 991, 997, -103
2162};
2163
2164/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002165 * Small divisors test (X must be positive)
2166 *
2167 * Return values:
2168 * 0: no small factor (possible prime, more tests needed)
2169 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002170 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002171 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002172 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002173static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002174{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002175 int ret = 0;
2176 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002178
Paul Bakker5121ce52009-01-03 21:22:43 +00002179 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002180 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002181
2182 for( i = 0; small_prime[i] > 0; i++ )
2183 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002185 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002186
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002187 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002188
2189 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002190 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002191 }
2192
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002193cleanup:
2194 return( ret );
2195}
2196
2197/*
2198 * Miller-Rabin pseudo-primality test (HAC 4.24)
2199 */
Janos Follath72d555d2018-09-03 14:45:23 +01002200static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002201 int (*f_rng)(void *, unsigned char *, size_t),
2202 void *p_rng )
2203{
Pascal Junodb99183d2015-03-11 16:49:45 +01002204 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002205 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002207
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002208 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2209 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002210
Paul Bakker5121ce52009-01-03 21:22:43 +00002211 /*
2212 * W = |X| - 1
2213 * R = W >> lsb( W )
2214 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002215 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2216 s = mbedtls_mpi_lsb( &W );
2217 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2218 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002219
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002220 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002221
Janos Follath72d555d2018-09-03 14:45:23 +01002222 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002223 {
2224 /*
2225 * pick a random A, 1 < A < |X| - 1
2226 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002227 count = 0;
2228 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002229 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002230
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002231 j = mbedtls_mpi_bitlen( &A );
2232 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002233 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002234 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002235 }
2236
2237 if (count++ > 30) {
Jens Wiklanderb2aa9382019-01-17 13:30:57 +01002238 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2239 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002240 }
2241
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002242 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2243 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002244
2245 /*
2246 * A = A^R mod |X|
2247 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002248 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002249
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002250 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2251 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002252 continue;
2253
2254 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002255 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002256 {
2257 /*
2258 * A = A * A mod |X|
2259 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002260 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2261 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002262
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002263 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002264 break;
2265
2266 j++;
2267 }
2268
2269 /*
2270 * not prime if A != |X| - 1 or A == 1
2271 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2273 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002274 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002275 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002276 break;
2277 }
2278 }
2279
2280cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002281 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2282 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002283
2284 return( ret );
2285}
2286
2287/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002288 * Pseudo-primality test: small factors, then Miller-Rabin
2289 */
Darryl Green94759f62018-10-16 15:09:19 +01002290static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002291 int (*f_rng)(void *, unsigned char *, size_t),
2292 void *p_rng )
2293{
2294 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002295 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002296
2297 XX.s = 1;
2298 XX.n = X->n;
2299 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002300
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002301 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2302 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2303 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002304
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002305 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002306 return( 0 );
2307
2308 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2309 {
2310 if( ret == 1 )
2311 return( 0 );
2312
2313 return( ret );
2314 }
2315
Janos Follath72d555d2018-09-03 14:45:23 +01002316 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2317}
2318
2319/*
2320 * Pseudo-primality test, error probability 2^-80
2321 */
2322int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2323 int (*f_rng)(void *, unsigned char *, size_t),
2324 void *p_rng )
2325{
2326 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002327}
2328
2329/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002330 * Prime number generation
2331 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002332int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002333 int (*f_rng)(void *, unsigned char *, size_t),
2334 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002335{
Paul Bakker23986e52011-04-24 08:57:21 +00002336 int ret;
2337 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002338 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002339 mbedtls_mpi_uint r;
2340 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2343 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002345 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
2347 n = BITS_TO_LIMBS( nbits );
2348
Janos Follath72d555d2018-09-03 14:45:23 +01002349 /*
2350 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2351 */
2352 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2353 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2354 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2355
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002356 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002357
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002358 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002359 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002361 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002362
2363 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002364
2365 if( dh_flag == 0 )
2366 {
Janos Follath72d555d2018-09-03 14:45:23 +01002367 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002368 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002369 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002370 goto cleanup;
2371
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002372 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002373 }
2374 }
2375 else
2376 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002377 /*
2378 * An necessary condition for Y and X = 2Y + 1 to be prime
2379 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2380 * Make sure it is satisfied, while keeping X = 3 mod 4
2381 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002382
2383 X->p[0] |= 2;
2384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002386 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002387 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002388 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002389 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002390
2391 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002392 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2393 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002394
2395 while( 1 )
2396 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002397 /*
2398 * First, check small factors for X and Y
2399 * before doing Miller-Rabin on any of them
2400 */
2401 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2402 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002403 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2404 == 0 &&
2405 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2406 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002407 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002408 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002409 }
2410
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002411 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002412 goto cleanup;
2413
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002414 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002415 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002416 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2417 * so up Y by 6 and X by 12.
2418 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002419 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2420 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002421 }
2422 }
2423
2424cleanup:
2425
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002426 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002427
2428 return( ret );
2429}
2430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002431#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002432
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002433#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002434
Paul Bakker23986e52011-04-24 08:57:21 +00002435#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002436
2437static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2438{
2439 { 693, 609, 21 },
2440 { 1764, 868, 28 },
2441 { 768454923, 542167814, 1 }
2442};
2443
Paul Bakker5121ce52009-01-03 21:22:43 +00002444/*
2445 * Checkup routine
2446 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002447int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002448{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002449 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002450 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002451
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002452 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2453 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002455 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002456 "EFE021C2645FD1DC586E69184AF4A31E" \
2457 "D5F53E93B5F123FA41680867BA110131" \
2458 "944FE7952E2517337780CB0DB80E61AA" \
2459 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002461 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002462 "B2E7EFD37075B9F03FF989C7C5051C20" \
2463 "34D2A323810251127E7BF8625A4F49A5" \
2464 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2465 "5B5C25763222FEFCCFC38B832366C29E" ) );
2466
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002467 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002468 "0066A198186C18C10B2F5ED9B522752A" \
2469 "9830B69916E535C8F047518A889A43A5" \
2470 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002472 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002473
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002474 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002475 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2476 "9E857EA95A03512E2BAE7391688D264A" \
2477 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2478 "8001B72E848A38CAE1C65F78E56ABDEF" \
2479 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2480 "ECF677152EF804370C1A305CAF3B5BF1" \
2481 "30879B56C61DE584A0F53A2447A51E" ) );
2482
2483 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002484 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002485
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002486 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002487 {
2488 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002489 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002490
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002491 ret = 1;
2492 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002493 }
2494
2495 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002496 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002497
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002498 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002499
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002500 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002501 "256567336059E52CAE22925474705F39A94" ) );
2502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002503 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002504 "6613F26162223DF488E9CD48CC132C7A" \
2505 "0AC93C701B001B092E4E5B9F73BCD27B" \
2506 "9EE50D0657C77F374E903CDFA4C642" ) );
2507
2508 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002509 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002511 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2512 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002513 {
2514 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002515 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002516
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002517 ret = 1;
2518 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002519 }
2520
2521 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002522 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002524 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002526 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002527 "36E139AEA55215609D2816998ED020BB" \
2528 "BD96C37890F65171D948E9BC7CBAA4D9" \
2529 "325D24D6A3C12710F10A09FA08AB87" ) );
2530
2531 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002532 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002533
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002534 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002535 {
2536 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002537 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002538
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002539 ret = 1;
2540 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002541 }
2542
2543 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002544 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002545
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002546 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002547
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002548 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002549 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2550 "C3DBA76456363A10869622EAC2DD84EC" \
2551 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2552
2553 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002554 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002555
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002556 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002557 {
2558 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002559 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002560
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002561 ret = 1;
2562 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002563 }
2564
2565 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002566 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002567
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002568 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002569 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002570
Paul Bakker66d5d072014-06-17 16:39:18 +02002571 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002572 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002573 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2574 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002576 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002578 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002579 {
2580 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002581 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002582
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002583 ret = 1;
2584 goto cleanup;
2585 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002586 }
2587
2588 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002589 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002590
Paul Bakker5121ce52009-01-03 21:22:43 +00002591cleanup:
2592
2593 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002594 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002595
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002596 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2597 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002598
2599 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002600 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002601
2602 return( ret );
2603}
2604
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002605#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002606
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002607#endif /* MBEDTLS_BIGNUM_C */