blob: f57b328ad2efca3ba57f93f13896b35682d17347 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000048
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <string.h>
50
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000052#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020053#else
Rich Evans00ab4702015-02-06 13:43:58 +000054#include <stdio.h>
55#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020057#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020059#endif
60
Paul Bakker34617722014-06-13 17:20:13 +020061/* Implementation that should never be optimized out by the compiler */
Alexey Skalozube17a8da2016-01-13 17:19:33 +020062static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) {
Alexey Skalozub3d53f412016-01-13 16:53:40 +020063 volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0;
Paul Bakker34617722014-06-13 17:20:13 +020064}
65
Hanno Becker88807112017-10-18 12:41:30 +010066/* Implementation that should never be optimized out by the compiler */
67static void mbedtls_zeroize( void *v, size_t n ) {
68 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
69}
70
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000072#define biL (ciL << 3) /* bits in limb */
73#define biH (ciL << 2) /* half limb size */
74
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010075#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
76
Paul Bakker5121ce52009-01-03 21:22:43 +000077/*
78 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020079 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000080 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020081#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
82#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000083
84/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000085 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000086 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020087void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000088{
Paul Bakker6c591fa2011-05-05 11:49:20 +000089 if( X == NULL )
90 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000091
Paul Bakker6c591fa2011-05-05 11:49:20 +000092 X->s = 1;
93 X->n = 0;
94 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000095}
96
97/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000098 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000099 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000101{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000102 if( X == NULL )
103 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000104
Paul Bakker6c591fa2011-05-05 11:49:20 +0000105 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000106 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200107 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200108 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000109 }
110
Paul Bakker6c591fa2011-05-05 11:49:20 +0000111 X->s = 1;
112 X->n = 0;
113 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000114}
115
116/*
117 * Enlarge to the specified number of limbs
118 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000120{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200123 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200124 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000125
Paul Bakker5121ce52009-01-03 21:22:43 +0000126 if( X->n < nblimbs )
127 {
Simon Butcher29176892016-05-20 00:19:09 +0100128 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200129 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000130
Paul Bakker5121ce52009-01-03 21:22:43 +0000131 if( X->p != NULL )
132 {
133 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200134 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000136 }
137
138 X->n = nblimbs;
139 X->p = p;
140 }
141
142 return( 0 );
143}
144
145/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100146 * Resize down as much as possible,
147 * while keeping at least the specified number of limbs
148 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100150{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152 size_t i;
153
154 /* Actually resize up in this case */
155 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100157
158 for( i = X->n - 1; i > 0; i-- )
159 if( X->p[i] != 0 )
160 break;
161 i++;
162
163 if( i < nblimbs )
164 i = nblimbs;
165
Simon Butcher29176892016-05-20 00:19:09 +0100166 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200167 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100168
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100169 if( X->p != NULL )
170 {
171 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200172 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100174 }
175
176 X->n = i;
177 X->p = p;
178
179 return( 0 );
180}
181
182/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000183 * Copy the contents of Y into X
184 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000186{
Paul Bakker23986e52011-04-24 08:57:21 +0000187 int ret;
188 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000189
190 if( X == Y )
191 return( 0 );
192
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200193 if( Y->p == NULL )
194 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200195 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200196 return( 0 );
197 }
198
Paul Bakker5121ce52009-01-03 21:22:43 +0000199 for( i = Y->n - 1; i > 0; i-- )
200 if( Y->p[i] != 0 )
201 break;
202 i++;
203
204 X->s = Y->s;
205
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000207
208 memset( X->p, 0, X->n * ciL );
209 memcpy( X->p, Y->p, i * ciL );
210
211cleanup:
212
213 return( ret );
214}
215
216/*
217 * Swap the contents of X and Y
218 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000220{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200223 memcpy( &T, X, sizeof( mbedtls_mpi ) );
224 memcpy( X, Y, sizeof( mbedtls_mpi ) );
225 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000226}
227
228/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100229 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100230 * about whether the assignment was made or not.
231 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100234{
235 int ret = 0;
236 size_t i;
237
Pascal Junodb99183d2015-03-11 16:49:45 +0100238 /* make sure assign is 0 or 1 in a time-constant manner */
239 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100242
Paul Bakker66d5d072014-06-17 16:39:18 +0200243 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100244
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100245 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200246 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100247
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100248 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200249 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250
251cleanup:
252 return( ret );
253}
254
255/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100256 * Conditionally swap X and Y, without leaking information
257 * about whether the swap was made or not.
258 * Here it is not ok to simply swap the pointers, which whould lead to
259 * different memory access patterns when X and Y are used afterwards.
260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100262{
263 int ret, s;
264 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100266
267 if( X == Y )
268 return( 0 );
269
Pascal Junodb99183d2015-03-11 16:49:45 +0100270 /* make sure swap is 0 or 1 in a time-constant manner */
271 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100272
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200273 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
274 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100275
276 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200277 X->s = X->s * ( 1 - swap ) + Y->s * swap;
278 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100279
280
281 for( i = 0; i < X->n; i++ )
282 {
283 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200284 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
285 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286 }
287
288cleanup:
289 return( ret );
290}
291
292/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000293 * Set value from integer
294 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200295int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000296{
297 int ret;
298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000300 memset( X->p, 0, X->n * ciL );
301
302 X->p[0] = ( z < 0 ) ? -z : z;
303 X->s = ( z < 0 ) ? -1 : 1;
304
305cleanup:
306
307 return( ret );
308}
309
310/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000311 * Get a specific bit
312 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200313int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000314{
315 if( X->n * biL <= pos )
316 return( 0 );
317
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200318 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000319}
320
Gilles Peskine220cc172018-11-20 16:47:47 +0100321/* Get a specific byte, without range checks. */
322#define GET_BYTE( X, i ) \
323 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
324
Paul Bakker2f5947e2011-05-18 15:47:11 +0000325/*
326 * Set a bit to a specific value of 0 or 1
327 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200328int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000329{
330 int ret = 0;
331 size_t off = pos / biL;
332 size_t idx = pos % biL;
333
334 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200335 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200336
Paul Bakker2f5947e2011-05-18 15:47:11 +0000337 if( X->n * biL <= pos )
338 {
339 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200340 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200342 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000343 }
344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200345 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
346 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000347
348cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200349
Paul Bakker2f5947e2011-05-18 15:47:11 +0000350 return( ret );
351}
352
353/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200354 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000355 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000357{
Paul Bakker23986e52011-04-24 08:57:21 +0000358 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000359
360 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000361 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000362 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
363 return( count );
364
365 return( 0 );
366}
367
368/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000369 * Count leading zero bits in a given integer
370 */
371static size_t mbedtls_clz( const mbedtls_mpi_uint x )
372{
373 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100374 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000375
376 for( j = 0; j < biL; j++ )
377 {
378 if( x & mask ) break;
379
380 mask >>= 1;
381 }
382
383 return j;
384}
385
386/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200387 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000388 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200389size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000390{
Paul Bakker23986e52011-04-24 08:57:21 +0000391 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000392
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200393 if( X->n == 0 )
394 return( 0 );
395
Paul Bakker5121ce52009-01-03 21:22:43 +0000396 for( i = X->n - 1; i > 0; i-- )
397 if( X->p[i] != 0 )
398 break;
399
Simon Butcher15b15d12015-11-26 19:35:03 +0000400 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000401
Paul Bakker23986e52011-04-24 08:57:21 +0000402 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000403}
404
405/*
406 * Return the total size in bytes
407 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000409{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200410 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000411}
412
413/*
414 * Convert an ASCII character to digit value
415 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000417{
418 *d = 255;
419
420 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
421 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
422 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424 if( *d >= (mbedtls_mpi_uint) radix )
425 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
427 return( 0 );
428}
429
430/*
431 * Import from an ASCII string
432 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000434{
Paul Bakker23986e52011-04-24 08:57:21 +0000435 int ret;
436 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437 mbedtls_mpi_uint d;
438 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000439
440 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200443 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000444
Paul Bakkerff60ee62010-03-16 21:09:09 +0000445 slen = strlen( s );
446
Paul Bakker5121ce52009-01-03 21:22:43 +0000447 if( radix == 16 )
448 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100449 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200450 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
451
Paul Bakkerff60ee62010-03-16 21:09:09 +0000452 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000453
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
455 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000456
Paul Bakker23986e52011-04-24 08:57:21 +0000457 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 {
Paul Bakker23986e52011-04-24 08:57:21 +0000459 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000460 {
461 X->s = -1;
462 break;
463 }
464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200466 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000467 }
468 }
469 else
470 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000472
Paul Bakkerff60ee62010-03-16 21:09:09 +0000473 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 {
475 if( i == 0 && s[i] == '-' )
476 {
477 X->s = -1;
478 continue;
479 }
480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
482 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000483
484 if( X->s == 1 )
485 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000487 }
488 else
489 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000491 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000492 }
493 }
494
495cleanup:
496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000498
499 return( ret );
500}
501
502/*
Ron Eldore6cbfc32018-11-20 14:07:01 +0200503 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000504 */
Ron Eldore6cbfc32018-11-20 14:07:01 +0200505static int mpi_write_hlp( mbedtls_mpi *X, int radix,
506 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000507{
508 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 mbedtls_mpi_uint r;
Ron Eldore6cbfc32018-11-20 14:07:01 +0200510 size_t length = 0;
511 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000512
Ron Eldore6cbfc32018-11-20 14:07:01 +0200513 do
514 {
515 if( length >= buflen )
516 {
517 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
518 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000519
Ron Eldore6cbfc32018-11-20 14:07:01 +0200520 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
521 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
522 /*
523 * Write the residue in the current position, as an ASCII character.
524 */
525 if( r < 0xA )
526 *(--p_end) = (char)( '0' + r );
527 else
528 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000529
Ron Eldore6cbfc32018-11-20 14:07:01 +0200530 length++;
531 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000532
Ron Eldore6cbfc32018-11-20 14:07:01 +0200533 memmove( *p, p_end, length );
534 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000535
536cleanup:
537
538 return( ret );
539}
540
541/*
542 * Export into an ASCII string
543 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100544int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
545 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000546{
Paul Bakker23986e52011-04-24 08:57:21 +0000547 int ret = 0;
548 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000549 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000551
552 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000554
Hanno Beckera277d4c2019-02-04 09:45:07 +0000555 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
556 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
557 * `n`. If radix > 4, this might be a strict
558 * overapproximation of the number of
559 * radix-adic digits needed to present `n`. */
560 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
561 * present `n`. */
562
Janos Follath216e7382019-03-06 13:43:02 +0000563 n += 1; /* Terminating null byte */
Hanno Beckera277d4c2019-02-04 09:45:07 +0000564 n += 1; /* Compensate for the divisions above, which round down `n`
565 * in case it's not even. */
566 n += 1; /* Potential '-'-sign. */
567 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
568 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000569
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100570 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000571 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100572 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000574 }
575
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100576 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000578
579 if( X->s == -1 )
Hanno Beckereff335d2019-02-01 16:41:30 +0000580 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000581 *p++ = '-';
Hanno Beckereff335d2019-02-01 16:41:30 +0000582 buflen--;
583 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
585 if( radix == 16 )
586 {
Paul Bakker23986e52011-04-24 08:57:21 +0000587 int c;
588 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000589
Paul Bakker23986e52011-04-24 08:57:21 +0000590 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000591 {
Paul Bakker23986e52011-04-24 08:57:21 +0000592 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000593 {
Paul Bakker23986e52011-04-24 08:57:21 +0000594 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000595
Paul Bakker6c343d72014-07-10 14:36:19 +0200596 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000597 continue;
598
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000599 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000600 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000601 k = 1;
602 }
603 }
604 }
605 else
606 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000608
609 if( T.s == -1 )
610 T.s = 1;
611
Ron Eldore6cbfc32018-11-20 14:07:01 +0200612 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000613 }
614
615 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100616 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000617
618cleanup:
619
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000621
622 return( ret );
623}
624
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200625#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000626/*
627 * Read X from an opened file
628 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000630{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000632 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000633 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000634 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000635 * Buffer should have space for (short) label and decimal formatted MPI,
636 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000637 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000639
640 memset( s, 0, sizeof( s ) );
641 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000643
644 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000645 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200646 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000647
Hanno Beckerb2034b72017-04-26 11:46:46 +0100648 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
649 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000650
651 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100652 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000653 if( mpi_get_digit( &d, radix, *p ) != 0 )
654 break;
655
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000657}
658
659/*
660 * Write X into an opened file (or stdout if fout == NULL)
661 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000663{
Paul Bakker23986e52011-04-24 08:57:21 +0000664 int ret;
665 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000666 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000667 * Buffer should have space for (short) label and decimal formatted MPI,
668 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000669 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000671
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100672 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000673
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100674 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000675
676 if( p == NULL ) p = "";
677
678 plen = strlen( p );
679 slen = strlen( s );
680 s[slen++] = '\r';
681 s[slen++] = '\n';
682
683 if( fout != NULL )
684 {
685 if( fwrite( p, 1, plen, fout ) != plen ||
686 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000688 }
689 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
692cleanup:
693
694 return( ret );
695}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000697
698/*
699 * Import X from unsigned binary data, big endian
700 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000702{
Paul Bakker23986e52011-04-24 08:57:21 +0000703 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100704 size_t i, j;
705 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000706
Hanno Becker073c1992017-10-17 15:17:27 +0100707 /* Ensure that target MPI has exactly the necessary number of limbs */
708 if( X->n != limbs )
709 {
710 mbedtls_mpi_free( X );
711 mbedtls_mpi_init( X );
712 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
713 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000714
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200715 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000716
Hanno Becker073c1992017-10-17 15:17:27 +0100717 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200718 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000719
720cleanup:
721
722 return( ret );
723}
724
725/*
726 * Export X into unsigned binary data, big endian
727 */
Gilles Peskine220cc172018-11-20 16:47:47 +0100728int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
729 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000730{
Gilles Peskine220cc172018-11-20 16:47:47 +0100731 size_t stored_bytes = X->n * ciL;
732 size_t bytes_to_copy;
733 unsigned char *p;
734 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000735
Gilles Peskine220cc172018-11-20 16:47:47 +0100736 if( stored_bytes < buflen )
737 {
738 /* There is enough space in the output buffer. Write initial
739 * null bytes and record the position at which to start
740 * writing the significant bytes. In this case, the execution
741 * trace of this function does not depend on the value of the
742 * number. */
743 bytes_to_copy = stored_bytes;
744 p = buf + buflen - stored_bytes;
745 memset( buf, 0, buflen - stored_bytes );
746 }
747 else
748 {
749 /* The output buffer is smaller than the allocated size of X.
750 * However X may fit if its leading bytes are zero. */
751 bytes_to_copy = buflen;
752 p = buf;
753 for( i = bytes_to_copy; i < stored_bytes; i++ )
754 {
755 if( GET_BYTE( X, i ) != 0 )
756 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
757 }
758 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000759
Gilles Peskine220cc172018-11-20 16:47:47 +0100760 for( i = 0; i < bytes_to_copy; i++ )
761 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000762
763 return( 0 );
764}
765
766/*
767 * Left-shift: X <<= count
768 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200769int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000770{
Paul Bakker23986e52011-04-24 08:57:21 +0000771 int ret;
772 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200773 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000774
775 v0 = count / (biL );
776 t1 = count & (biL - 1);
777
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200778 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000779
Paul Bakkerf9688572011-05-05 10:00:45 +0000780 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200781 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000782
783 ret = 0;
784
785 /*
786 * shift by count / limb_size
787 */
788 if( v0 > 0 )
789 {
Paul Bakker23986e52011-04-24 08:57:21 +0000790 for( i = X->n; i > v0; i-- )
791 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000792
Paul Bakker23986e52011-04-24 08:57:21 +0000793 for( ; i > 0; i-- )
794 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000795 }
796
797 /*
798 * shift by count % limb_size
799 */
800 if( t1 > 0 )
801 {
802 for( i = v0; i < X->n; i++ )
803 {
804 r1 = X->p[i] >> (biL - t1);
805 X->p[i] <<= t1;
806 X->p[i] |= r0;
807 r0 = r1;
808 }
809 }
810
811cleanup:
812
813 return( ret );
814}
815
816/*
817 * Right-shift: X >>= count
818 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200819int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000820{
Paul Bakker23986e52011-04-24 08:57:21 +0000821 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200822 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000823
824 v0 = count / biL;
825 v1 = count & (biL - 1);
826
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100827 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200828 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100829
Paul Bakker5121ce52009-01-03 21:22:43 +0000830 /*
831 * shift by count / limb_size
832 */
833 if( v0 > 0 )
834 {
835 for( i = 0; i < X->n - v0; i++ )
836 X->p[i] = X->p[i + v0];
837
838 for( ; i < X->n; i++ )
839 X->p[i] = 0;
840 }
841
842 /*
843 * shift by count % limb_size
844 */
845 if( v1 > 0 )
846 {
Paul Bakker23986e52011-04-24 08:57:21 +0000847 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000848 {
Paul Bakker23986e52011-04-24 08:57:21 +0000849 r1 = X->p[i - 1] << (biL - v1);
850 X->p[i - 1] >>= v1;
851 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000852 r0 = r1;
853 }
854 }
855
856 return( 0 );
857}
858
859/*
860 * Compare unsigned values
861 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200862int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000863{
Paul Bakker23986e52011-04-24 08:57:21 +0000864 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000865
Paul Bakker23986e52011-04-24 08:57:21 +0000866 for( i = X->n; i > 0; i-- )
867 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000868 break;
869
Paul Bakker23986e52011-04-24 08:57:21 +0000870 for( j = Y->n; j > 0; j-- )
871 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000872 break;
873
Paul Bakker23986e52011-04-24 08:57:21 +0000874 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000875 return( 0 );
876
877 if( i > j ) return( 1 );
878 if( j > i ) return( -1 );
879
Paul Bakker23986e52011-04-24 08:57:21 +0000880 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000881 {
Paul Bakker23986e52011-04-24 08:57:21 +0000882 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
883 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000884 }
885
886 return( 0 );
887}
888
889/*
890 * Compare signed values
891 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200892int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000893{
Paul Bakker23986e52011-04-24 08:57:21 +0000894 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000895
Paul Bakker23986e52011-04-24 08:57:21 +0000896 for( i = X->n; i > 0; i-- )
897 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000898 break;
899
Paul Bakker23986e52011-04-24 08:57:21 +0000900 for( j = Y->n; j > 0; j-- )
901 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000902 break;
903
Paul Bakker23986e52011-04-24 08:57:21 +0000904 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000905 return( 0 );
906
907 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000908 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000909
910 if( X->s > 0 && Y->s < 0 ) return( 1 );
911 if( Y->s > 0 && X->s < 0 ) return( -1 );
912
Paul Bakker23986e52011-04-24 08:57:21 +0000913 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000914 {
Paul Bakker23986e52011-04-24 08:57:21 +0000915 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
916 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000917 }
918
919 return( 0 );
920}
921
Janos Follathe0187b92019-09-05 14:47:19 +0100922static int ct_lt_mpi_uint( const mbedtls_mpi_uint x, const mbedtls_mpi_uint y )
923{
924 mbedtls_mpi_uint ret;
925 mbedtls_mpi_uint cond;
926
927 /*
928 * Check if the most significant bits (MSB) of the operands are different.
929 */
930 cond = ( x ^ y );
931 /*
932 * If the MSB are the same then the difference x-y will be negative (and
933 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
934 */
935 ret = ( x - y ) & ~cond;
936 /*
937 * If the MSB are different, then the operand with the MSB of 1 is the
938 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
939 * the MSB of y is 0.)
940 */
941 ret |= y & cond;
942
943
944 ret = ret >> ( sizeof( mbedtls_mpi_uint ) * 8 - 1 );
945
946 return ret;
947}
948
Janos Follath8461c0e2019-10-11 10:43:40 +0100949static int ct_bool_get_mask( unsigned int b )
950{
951 return ~( b - 1 );
952}
953
Janos Follathe0187b92019-09-05 14:47:19 +0100954/*
955 * Compare signed values in constant time
956 */
957int mbedtls_mpi_cmp_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
958 int *ret )
959{
960 size_t i;
Janos Follathc587a322019-09-23 09:19:14 +0100961 unsigned int cond, done, sign_X, sign_Y;
Janos Follathe0187b92019-09-05 14:47:19 +0100962
963 if( X->n != Y->n )
964 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
965
966 /*
967 * if( X->s > 0 && Y->s < 0 )
968 * {
969 * *ret = 1;
970 * done = 1;
971 * }
972 * else if( Y->s > 0 && X->s < 0 )
973 * {
974 * *ret = -1;
975 * done = 1;
976 * }
977 */
Janos Follathc587a322019-09-23 09:19:14 +0100978 sign_X = X->s;
979 sign_Y = Y->s;
Janos Follathe0187b92019-09-05 14:47:19 +0100980 cond = ( ( sign_X ^ sign_Y ) >> ( sizeof( unsigned int ) * 8 - 1 ) );
Janos Follath8461c0e2019-10-11 10:43:40 +0100981 *ret = ct_bool_get_mask( cond ) & X->s;
Janos Follathe0187b92019-09-05 14:47:19 +0100982 done = cond;
983
984 for( i = X->n; i > 0; i-- )
985 {
986 /*
987 * if( ( X->p[i - 1] > Y->p[i - 1] ) && !done )
988 * {
989 * done = 1;
990 * *ret = X->s;
991 * }
992 */
993 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
Janos Follath8461c0e2019-10-11 10:43:40 +0100994 *ret |= ct_bool_get_mask( cond & ( 1 - done ) ) & X->s;
995 done |= cond & ( 1 - done );
Janos Follathe0187b92019-09-05 14:47:19 +0100996
997 /*
998 * if( ( X->p[i - 1] < Y->p[i - 1] ) && !done )
999 * {
1000 * done = 1;
1001 * *ret = -X->s;
1002 * }
1003 */
1004 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
Janos Follath8461c0e2019-10-11 10:43:40 +01001005 *ret |= ct_bool_get_mask( cond & ( 1 - done ) ) & -X->s;
1006 done |= cond & ( 1 - done );
Janos Follathe0187b92019-09-05 14:47:19 +01001007 }
1008
1009 return( 0 );
1010}
1011
Paul Bakker5121ce52009-01-03 21:22:43 +00001012/*
1013 * Compare signed values
1014 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001015int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001016{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001017 mbedtls_mpi Y;
1018 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001019
1020 *p = ( z < 0 ) ? -z : z;
1021 Y.s = ( z < 0 ) ? -1 : 1;
1022 Y.n = 1;
1023 Y.p = p;
1024
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001025 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001026}
1027
1028/*
1029 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1030 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001031int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001032{
Paul Bakker23986e52011-04-24 08:57:21 +00001033 int ret;
1034 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001035 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +00001036
1037 if( X == B )
1038 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001039 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001040 }
1041
1042 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001043 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001044
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001045 /*
1046 * X should always be positive as a result of unsigned additions.
1047 */
1048 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001049
Paul Bakker23986e52011-04-24 08:57:21 +00001050 for( j = B->n; j > 0; j-- )
1051 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001052 break;
1053
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001054 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001055
1056 o = B->p; p = X->p; c = 0;
1057
Janos Follath6c922682015-10-30 17:43:11 +01001058 /*
1059 * tmp is used because it might happen that p == o
1060 */
Paul Bakker23986e52011-04-24 08:57:21 +00001061 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001062 {
Janos Follath6c922682015-10-30 17:43:11 +01001063 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001064 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001065 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001066 }
1067
1068 while( c != 0 )
1069 {
1070 if( i >= X->n )
1071 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001072 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001073 p = X->p + i;
1074 }
1075
Paul Bakker2d319fd2012-09-16 21:34:26 +00001076 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001077 }
1078
1079cleanup:
1080
1081 return( ret );
1082}
1083
1084/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001085 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001086 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001087static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001088{
Paul Bakker23986e52011-04-24 08:57:21 +00001089 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001090 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001091
1092 for( i = c = 0; i < n; i++, s++, d++ )
1093 {
1094 z = ( *d < c ); *d -= c;
1095 c = ( *d < *s ) + z; *d -= *s;
1096 }
1097
1098 while( c != 0 )
1099 {
1100 z = ( *d < c ); *d -= c;
1101 c = z; i++; d++;
1102 }
1103}
1104
1105/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001106 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001107 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001108int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001109{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001110 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001111 int ret;
1112 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001113
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001114 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1115 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001116
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001117 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001118
1119 if( X == B )
1120 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001121 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001122 B = &TB;
1123 }
1124
1125 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001126 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001127
Paul Bakker1ef7a532009-06-20 10:50:55 +00001128 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001129 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001130 */
1131 X->s = 1;
1132
Paul Bakker5121ce52009-01-03 21:22:43 +00001133 ret = 0;
1134
Paul Bakker23986e52011-04-24 08:57:21 +00001135 for( n = B->n; n > 0; n-- )
1136 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001137 break;
1138
Paul Bakker23986e52011-04-24 08:57:21 +00001139 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001140
1141cleanup:
1142
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001143 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001144
1145 return( ret );
1146}
1147
1148/*
1149 * Signed addition: X = A + B
1150 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001151int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001152{
1153 int ret, s = A->s;
1154
1155 if( A->s * B->s < 0 )
1156 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001157 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001158 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001159 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001160 X->s = s;
1161 }
1162 else
1163 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001164 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001165 X->s = -s;
1166 }
1167 }
1168 else
1169 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001170 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001171 X->s = s;
1172 }
1173
1174cleanup:
1175
1176 return( ret );
1177}
1178
1179/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001180 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001181 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001182int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001183{
1184 int ret, s = A->s;
1185
1186 if( A->s * B->s > 0 )
1187 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001188 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001189 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001190 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001191 X->s = s;
1192 }
1193 else
1194 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001195 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001196 X->s = -s;
1197 }
1198 }
1199 else
1200 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001201 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001202 X->s = s;
1203 }
1204
1205cleanup:
1206
1207 return( ret );
1208}
1209
1210/*
1211 * Signed addition: X = A + b
1212 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001213int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001214{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001215 mbedtls_mpi _B;
1216 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001217
1218 p[0] = ( b < 0 ) ? -b : b;
1219 _B.s = ( b < 0 ) ? -1 : 1;
1220 _B.n = 1;
1221 _B.p = p;
1222
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001223 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001224}
1225
1226/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001227 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001228 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001229int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001230{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001231 mbedtls_mpi _B;
1232 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001233
1234 p[0] = ( b < 0 ) ? -b : b;
1235 _B.s = ( b < 0 ) ? -1 : 1;
1236 _B.n = 1;
1237 _B.p = p;
1238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001239 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001240}
1241
1242/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001243 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001244 */
1245static
1246#if defined(__APPLE__) && defined(__arm__)
1247/*
1248 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1249 * appears to need this to prevent bad ARM code generation at -O3.
1250 */
1251__attribute__ ((noinline))
1252#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001253void 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 +00001254{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001255 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001256
1257#if defined(MULADDC_HUIT)
1258 for( ; i >= 8; i -= 8 )
1259 {
1260 MULADDC_INIT
1261 MULADDC_HUIT
1262 MULADDC_STOP
1263 }
1264
1265 for( ; i > 0; i-- )
1266 {
1267 MULADDC_INIT
1268 MULADDC_CORE
1269 MULADDC_STOP
1270 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001271#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001272 for( ; i >= 16; i -= 16 )
1273 {
1274 MULADDC_INIT
1275 MULADDC_CORE MULADDC_CORE
1276 MULADDC_CORE MULADDC_CORE
1277 MULADDC_CORE MULADDC_CORE
1278 MULADDC_CORE MULADDC_CORE
1279
1280 MULADDC_CORE MULADDC_CORE
1281 MULADDC_CORE MULADDC_CORE
1282 MULADDC_CORE MULADDC_CORE
1283 MULADDC_CORE MULADDC_CORE
1284 MULADDC_STOP
1285 }
1286
1287 for( ; i >= 8; i -= 8 )
1288 {
1289 MULADDC_INIT
1290 MULADDC_CORE MULADDC_CORE
1291 MULADDC_CORE MULADDC_CORE
1292
1293 MULADDC_CORE MULADDC_CORE
1294 MULADDC_CORE MULADDC_CORE
1295 MULADDC_STOP
1296 }
1297
1298 for( ; i > 0; i-- )
1299 {
1300 MULADDC_INIT
1301 MULADDC_CORE
1302 MULADDC_STOP
1303 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001304#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001305
1306 t++;
1307
1308 do {
1309 *d += c; c = ( *d < c ); d++;
1310 }
1311 while( c != 0 );
1312}
1313
1314/*
1315 * Baseline multiplication: X = A * B (HAC 14.12)
1316 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001317int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001318{
Paul Bakker23986e52011-04-24 08:57:21 +00001319 int ret;
1320 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001321 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001322
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001323 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001324
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001325 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1326 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001327
Paul Bakker23986e52011-04-24 08:57:21 +00001328 for( i = A->n; i > 0; i-- )
1329 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001330 break;
1331
Paul Bakker23986e52011-04-24 08:57:21 +00001332 for( j = B->n; j > 0; j-- )
1333 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001334 break;
1335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1337 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001338
Paul Bakker23986e52011-04-24 08:57:21 +00001339 for( i++; j > 0; j-- )
1340 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001341
1342 X->s = A->s * B->s;
1343
1344cleanup:
1345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001346 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001347
1348 return( ret );
1349}
1350
1351/*
1352 * Baseline multiplication: X = A * b
1353 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001354int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001355{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001356 mbedtls_mpi _B;
1357 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001358
1359 _B.s = 1;
1360 _B.n = 1;
1361 _B.p = p;
1362 p[0] = b;
1363
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001364 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001365}
1366
1367/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001368 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1369 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001370 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001371static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1372 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001373{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001374#if defined(MBEDTLS_HAVE_UDBL)
1375 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001376#else
Simon Butcher9803d072016-01-03 00:24:34 +00001377 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1378 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001379 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1380 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001381 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001382#endif
1383
Simon Butcher15b15d12015-11-26 19:35:03 +00001384 /*
1385 * Check for overflow
1386 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001387 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001388 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001389 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001390
Simon Butcherf5ba0452015-12-27 23:01:55 +00001391 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001392 }
1393
1394#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001395 dividend = (mbedtls_t_udbl) u1 << biL;
1396 dividend |= (mbedtls_t_udbl) u0;
1397 quotient = dividend / d;
1398 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1399 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1400
1401 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001402 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001403
1404 return (mbedtls_mpi_uint) quotient;
1405#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001406
1407 /*
1408 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1409 * Vol. 2 - Seminumerical Algorithms, Knuth
1410 */
1411
1412 /*
1413 * Normalize the divisor, d, and dividend, u0, u1
1414 */
1415 s = mbedtls_clz( d );
1416 d = d << s;
1417
1418 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001419 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001420 u0 = u0 << s;
1421
1422 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001423 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001424
1425 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001426 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001427
1428 /*
1429 * Find the first quotient and remainder
1430 */
1431 q1 = u1 / d1;
1432 r0 = u1 - d1 * q1;
1433
1434 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1435 {
1436 q1 -= 1;
1437 r0 += d1;
1438
1439 if ( r0 >= radix ) break;
1440 }
1441
Simon Butcherf5ba0452015-12-27 23:01:55 +00001442 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001443 q0 = rAX / d1;
1444 r0 = rAX - q0 * d1;
1445
1446 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1447 {
1448 q0 -= 1;
1449 r0 += d1;
1450
1451 if ( r0 >= radix ) break;
1452 }
1453
1454 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001455 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001456
1457 quotient = q1 * radix + q0;
1458
1459 return quotient;
1460#endif
1461}
1462
1463/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001464 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001465 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466int 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 +00001467{
Paul Bakker23986e52011-04-24 08:57:21 +00001468 int ret;
1469 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001470 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001472 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1473 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001474
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001475 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1476 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001477
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001478 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001479 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001480 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1481 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001482 return( 0 );
1483 }
1484
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001485 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1486 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001487 X.s = Y.s = 1;
1488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001489 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1490 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1491 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1492 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001493
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001494 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001495 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001496 {
1497 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001498 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1499 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001500 }
1501 else k = 0;
1502
1503 n = X.n - 1;
1504 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001505 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001507 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001508 {
1509 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001510 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001511 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001512 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001513
1514 for( i = n; i > t ; i-- )
1515 {
1516 if( X.p[i] >= Y.p[t] )
1517 Z.p[i - t - 1] = ~0;
1518 else
1519 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001520 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1521 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001522 }
1523
1524 Z.p[i - t - 1]++;
1525 do
1526 {
1527 Z.p[i - t - 1]--;
1528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001529 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001530 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001531 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001532 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001533
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001534 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001535 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1536 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001537 T2.p[2] = X.p[i];
1538 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001540
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001541 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1542 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1543 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001544
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001545 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001546 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001547 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1548 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1549 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001550 Z.p[i - t - 1]--;
1551 }
1552 }
1553
1554 if( Q != NULL )
1555 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001556 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001557 Q->s = A->s * B->s;
1558 }
1559
1560 if( R != NULL )
1561 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001562 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001563 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001564 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001565
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001566 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001567 R->s = 1;
1568 }
1569
1570cleanup:
1571
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001572 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1573 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001574
1575 return( ret );
1576}
1577
1578/*
1579 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001580 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001581int 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 +00001582{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001583 mbedtls_mpi _B;
1584 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001585
1586 p[0] = ( b < 0 ) ? -b : b;
1587 _B.s = ( b < 0 ) ? -1 : 1;
1588 _B.n = 1;
1589 _B.p = p;
1590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001591 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001592}
1593
1594/*
1595 * Modulo: R = A mod B
1596 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001597int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001598{
1599 int ret;
1600
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001601 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1602 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001603
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001604 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001605
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001606 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1607 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001608
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001609 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1610 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001611
1612cleanup:
1613
1614 return( ret );
1615}
1616
1617/*
1618 * Modulo: r = A mod b
1619 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001620int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001621{
Paul Bakker23986e52011-04-24 08:57:21 +00001622 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001623 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001624
1625 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001626 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001627
1628 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001629 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001630
1631 /*
1632 * handle trivial cases
1633 */
1634 if( b == 1 )
1635 {
1636 *r = 0;
1637 return( 0 );
1638 }
1639
1640 if( b == 2 )
1641 {
1642 *r = A->p[0] & 1;
1643 return( 0 );
1644 }
1645
1646 /*
1647 * general case
1648 */
Paul Bakker23986e52011-04-24 08:57:21 +00001649 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001650 {
Paul Bakker23986e52011-04-24 08:57:21 +00001651 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001652 y = ( y << biH ) | ( x >> biH );
1653 z = y / b;
1654 y -= z * b;
1655
1656 x <<= biH;
1657 y = ( y << biH ) | ( x >> biH );
1658 z = y / b;
1659 y -= z * b;
1660 }
1661
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001662 /*
1663 * If A is negative, then the current y represents a negative value.
1664 * Flipping it to the positive side.
1665 */
1666 if( A->s < 0 && y != 0 )
1667 y = b - y;
1668
Paul Bakker5121ce52009-01-03 21:22:43 +00001669 *r = y;
1670
1671 return( 0 );
1672}
1673
1674/*
1675 * Fast Montgomery initialization (thanks to Tom St Denis)
1676 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001677static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001678{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001679 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001680 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001681
1682 x = m0;
1683 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001684
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001685 for( i = biL; i >= 8; i /= 2 )
1686 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001687
1688 *mm = ~x + 1;
1689}
1690
1691/*
1692 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1693 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001694static 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 +02001695 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001696{
Paul Bakker23986e52011-04-24 08:57:21 +00001697 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001698 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001699
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001700 if( T->n < N->n + 1 || T->p == NULL )
1701 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1702
Paul Bakker5121ce52009-01-03 21:22:43 +00001703 memset( T->p, 0, T->n * ciL );
1704
1705 d = T->p;
1706 n = N->n;
1707 m = ( B->n < n ) ? B->n : n;
1708
1709 for( i = 0; i < n; i++ )
1710 {
1711 /*
1712 * T = (T + u0*B + u1*N) / 2^biL
1713 */
1714 u0 = A->p[i];
1715 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1716
1717 mpi_mul_hlp( m, B->p, d, u0 );
1718 mpi_mul_hlp( n, N->p, d, u1 );
1719
1720 *d++ = u0; d[n + 1] = 0;
1721 }
1722
Paul Bakker66d5d072014-06-17 16:39:18 +02001723 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001724
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001725 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001726 mpi_sub_hlp( n, N->p, A->p );
1727 else
1728 /* prevent timing attacks */
1729 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001730
1731 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001732}
1733
1734/*
1735 * Montgomery reduction: A = A * R^-1 mod N
1736 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001737static 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 +00001738{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001739 mbedtls_mpi_uint z = 1;
1740 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001741
Paul Bakker8ddb6452013-02-27 14:56:33 +01001742 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001743 U.p = &z;
1744
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001745 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001746}
1747
1748/*
1749 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1750 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001751int 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 +00001752{
Paul Bakker23986e52011-04-24 08:57:21 +00001753 int ret;
1754 size_t wbits, wsize, one = 1;
1755 size_t i, j, nblimbs;
1756 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001757 mbedtls_mpi_uint ei, mm, state;
1758 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001759 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001760
Hanno Becker930ec7d2018-03-09 10:48:00 +00001761 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001762 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001763
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001764 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1765 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001766
1767 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001768 * Init temps and window size
1769 */
1770 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001771 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1772 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001773 memset( W, 0, sizeof( W ) );
1774
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001775 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001776
1777 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1778 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1779
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001780#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001781 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1782 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001783#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001784
Paul Bakker5121ce52009-01-03 21:22:43 +00001785 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001786 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1787 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1788 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001789
1790 /*
Paul Bakker50546922012-05-19 08:40:49 +00001791 * Compensate for negative A (and correct at the end)
1792 */
1793 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001794 if( neg )
1795 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001796 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001797 Apos.s = 1;
1798 A = &Apos;
1799 }
1800
1801 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001802 * If 1st call, pre-compute R^2 mod N
1803 */
1804 if( _RR == NULL || _RR->p == NULL )
1805 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001806 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1807 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1808 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001809
1810 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001811 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001812 }
1813 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001814 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001815
1816 /*
1817 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1818 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001819 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1820 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001821 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001822 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001823
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001824 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001825
1826 /*
1827 * X = R^2 * R^-1 mod N = R mod N
1828 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001829 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001830 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001831
1832 if( wsize > 1 )
1833 {
1834 /*
1835 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1836 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001837 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001838
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001839 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1840 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001841
1842 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001843 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001844
Paul Bakker5121ce52009-01-03 21:22:43 +00001845 /*
1846 * W[i] = W[i - 1] * W[1]
1847 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001848 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001849 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001850 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1851 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001852
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001853 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001854 }
1855 }
1856
1857 nblimbs = E->n;
1858 bufsize = 0;
1859 nbits = 0;
1860 wbits = 0;
1861 state = 0;
1862
1863 while( 1 )
1864 {
1865 if( bufsize == 0 )
1866 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001867 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001868 break;
1869
Paul Bakker0d7702c2013-10-29 16:18:35 +01001870 nblimbs--;
1871
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001872 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001873 }
1874
1875 bufsize--;
1876
1877 ei = (E->p[nblimbs] >> bufsize) & 1;
1878
1879 /*
1880 * skip leading 0s
1881 */
1882 if( ei == 0 && state == 0 )
1883 continue;
1884
1885 if( ei == 0 && state == 1 )
1886 {
1887 /*
1888 * out of window, square X
1889 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001890 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001891 continue;
1892 }
1893
1894 /*
1895 * add ei to current window
1896 */
1897 state = 2;
1898
1899 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001900 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001901
1902 if( nbits == wsize )
1903 {
1904 /*
1905 * X = X^wsize R^-1 mod N
1906 */
1907 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001908 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001909
1910 /*
1911 * X = X * W[wbits] R^-1 mod N
1912 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001913 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001914
1915 state--;
1916 nbits = 0;
1917 wbits = 0;
1918 }
1919 }
1920
1921 /*
1922 * process the remaining bits
1923 */
1924 for( i = 0; i < nbits; i++ )
1925 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001926 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001927
1928 wbits <<= 1;
1929
Paul Bakker66d5d072014-06-17 16:39:18 +02001930 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001931 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001932 }
1933
1934 /*
1935 * X = A^E * R * R^-1 mod N = A^E mod N
1936 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001937 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001938
Hanno Beckera4af1c42017-04-18 09:07:45 +01001939 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001940 {
1941 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001942 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001943 }
1944
Paul Bakker5121ce52009-01-03 21:22:43 +00001945cleanup:
1946
Paul Bakker66d5d072014-06-17 16:39:18 +02001947 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001948 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001949
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001950 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001951
Paul Bakker75a28602014-03-31 12:08:17 +02001952 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001953 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001954
1955 return( ret );
1956}
1957
Paul Bakker5121ce52009-01-03 21:22:43 +00001958/*
1959 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1960 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001961int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001962{
Paul Bakker23986e52011-04-24 08:57:21 +00001963 int ret;
1964 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001965 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001966
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001967 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001968
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001969 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1970 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001971
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001972 lz = mbedtls_mpi_lsb( &TA );
1973 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001974
Paul Bakker66d5d072014-06-17 16:39:18 +02001975 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001976 lz = lzt;
1977
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001978 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1979 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001980
Paul Bakker5121ce52009-01-03 21:22:43 +00001981 TA.s = TB.s = 1;
1982
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001983 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001984 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001985 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1986 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001987
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001989 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001990 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1991 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001992 }
1993 else
1994 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001995 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1996 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001997 }
1998 }
1999
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002000 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2001 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002002
2003cleanup:
2004
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002005 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002006
2007 return( ret );
2008}
2009
Paul Bakker33dc46b2014-04-30 16:11:39 +02002010/*
2011 * Fill X with size bytes of random.
2012 *
2013 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002014 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002015 * deterministic, eg for tests).
2016 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002017int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002018 int (*f_rng)(void *, unsigned char *, size_t),
2019 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002020{
Paul Bakker23986e52011-04-24 08:57:21 +00002021 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002022 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02002023
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002024 if( size > MBEDTLS_MPI_MAX_SIZE )
2025 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002026
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002027 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2028 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002029
2030cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01002031 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002032 return( ret );
2033}
2034
Paul Bakker5121ce52009-01-03 21:22:43 +00002035/*
2036 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2037 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002038int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002039{
2040 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002041 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002042
Hanno Becker4bcb4912017-04-18 15:49:39 +01002043 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002044 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002045
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2047 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2048 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002049
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002050 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002051
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002053 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002054 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002055 goto cleanup;
2056 }
2057
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2059 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2060 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2061 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002062
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002063 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2064 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2065 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2066 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002067
2068 do
2069 {
2070 while( ( TU.p[0] & 1 ) == 0 )
2071 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002072 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002073
2074 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2075 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2077 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002078 }
2079
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002080 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2081 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002082 }
2083
2084 while( ( TV.p[0] & 1 ) == 0 )
2085 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002086 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002087
2088 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2089 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002090 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2091 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002092 }
2093
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002094 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2095 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002096 }
2097
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002098 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002099 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002100 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2101 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2102 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002103 }
2104 else
2105 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002106 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2107 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2108 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002109 }
2110 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002111 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002113 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2114 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002115
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002116 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2117 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002119 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002120
2121cleanup:
2122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002123 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2124 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2125 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002126
2127 return( ret );
2128}
2129
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002130#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002131
Paul Bakker5121ce52009-01-03 21:22:43 +00002132static const int small_prime[] =
2133{
2134 3, 5, 7, 11, 13, 17, 19, 23,
2135 29, 31, 37, 41, 43, 47, 53, 59,
2136 61, 67, 71, 73, 79, 83, 89, 97,
2137 101, 103, 107, 109, 113, 127, 131, 137,
2138 139, 149, 151, 157, 163, 167, 173, 179,
2139 181, 191, 193, 197, 199, 211, 223, 227,
2140 229, 233, 239, 241, 251, 257, 263, 269,
2141 271, 277, 281, 283, 293, 307, 311, 313,
2142 317, 331, 337, 347, 349, 353, 359, 367,
2143 373, 379, 383, 389, 397, 401, 409, 419,
2144 421, 431, 433, 439, 443, 449, 457, 461,
2145 463, 467, 479, 487, 491, 499, 503, 509,
2146 521, 523, 541, 547, 557, 563, 569, 571,
2147 577, 587, 593, 599, 601, 607, 613, 617,
2148 619, 631, 641, 643, 647, 653, 659, 661,
2149 673, 677, 683, 691, 701, 709, 719, 727,
2150 733, 739, 743, 751, 757, 761, 769, 773,
2151 787, 797, 809, 811, 821, 823, 827, 829,
2152 839, 853, 857, 859, 863, 877, 881, 883,
2153 887, 907, 911, 919, 929, 937, 941, 947,
2154 953, 967, 971, 977, 983, 991, 997, -103
2155};
2156
2157/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002158 * Small divisors test (X must be positive)
2159 *
2160 * Return values:
2161 * 0: no small factor (possible prime, more tests needed)
2162 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002163 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002164 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002165 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002166static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002167{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002168 int ret = 0;
2169 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002170 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002171
Paul Bakker5121ce52009-01-03 21:22:43 +00002172 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002173 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002174
2175 for( i = 0; small_prime[i] > 0; i++ )
2176 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002178 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002180 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002181
2182 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002183 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002184 }
2185
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002186cleanup:
2187 return( ret );
2188}
2189
2190/*
2191 * Miller-Rabin pseudo-primality test (HAC 4.24)
2192 */
Janos Follath72d555d2018-09-03 14:45:23 +01002193static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002194 int (*f_rng)(void *, unsigned char *, size_t),
2195 void *p_rng )
2196{
Pascal Junodb99183d2015-03-11 16:49:45 +01002197 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002198 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002199 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002201 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2202 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002203
Paul Bakker5121ce52009-01-03 21:22:43 +00002204 /*
2205 * W = |X| - 1
2206 * R = W >> lsb( W )
2207 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002208 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2209 s = mbedtls_mpi_lsb( &W );
2210 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2211 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002212
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002213 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002214
Janos Follath72d555d2018-09-03 14:45:23 +01002215 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002216 {
2217 /*
2218 * pick a random A, 1 < A < |X| - 1
2219 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002220 count = 0;
2221 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002222 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002223
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002224 j = mbedtls_mpi_bitlen( &A );
2225 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002226 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002227 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002228 }
2229
2230 if (count++ > 30) {
Jens Wiklanderb2aa9382019-01-17 13:30:57 +01002231 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2232 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002233 }
2234
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002235 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2236 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002237
2238 /*
2239 * A = A^R mod |X|
2240 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002241 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002242
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002243 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2244 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002245 continue;
2246
2247 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002248 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002249 {
2250 /*
2251 * A = A * A mod |X|
2252 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002253 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2254 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002255
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002256 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002257 break;
2258
2259 j++;
2260 }
2261
2262 /*
2263 * not prime if A != |X| - 1 or A == 1
2264 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002265 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2266 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002267 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002268 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002269 break;
2270 }
2271 }
2272
2273cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002274 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2275 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002276
2277 return( ret );
2278}
2279
2280/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002281 * Pseudo-primality test: small factors, then Miller-Rabin
2282 */
Darryl Green94759f62018-10-16 15:09:19 +01002283static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002284 int (*f_rng)(void *, unsigned char *, size_t),
2285 void *p_rng )
2286{
2287 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002289
2290 XX.s = 1;
2291 XX.n = X->n;
2292 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002294 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2295 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2296 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002297
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002298 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002299 return( 0 );
2300
2301 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2302 {
2303 if( ret == 1 )
2304 return( 0 );
2305
2306 return( ret );
2307 }
2308
Janos Follath72d555d2018-09-03 14:45:23 +01002309 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2310}
2311
2312/*
2313 * Pseudo-primality test, error probability 2^-80
2314 */
2315int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2316 int (*f_rng)(void *, unsigned char *, size_t),
2317 void *p_rng )
2318{
2319 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002320}
2321
2322/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002323 * Prime number generation
2324 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002325int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002326 int (*f_rng)(void *, unsigned char *, size_t),
2327 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002328{
Paul Bakker23986e52011-04-24 08:57:21 +00002329 int ret;
2330 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002331 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002332 mbedtls_mpi_uint r;
2333 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2336 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002339
2340 n = BITS_TO_LIMBS( nbits );
2341
Janos Follath72d555d2018-09-03 14:45:23 +01002342 /*
2343 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2344 */
2345 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2346 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2347 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002349 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002350
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002351 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002352 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002353
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002354 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002355
2356 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002357
2358 if( dh_flag == 0 )
2359 {
Janos Follath72d555d2018-09-03 14:45:23 +01002360 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002361 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002362 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002363 goto cleanup;
2364
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002365 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002366 }
2367 }
2368 else
2369 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002370 /*
2371 * An necessary condition for Y and X = 2Y + 1 to be prime
2372 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2373 * Make sure it is satisfied, while keeping X = 3 mod 4
2374 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002375
2376 X->p[0] |= 2;
2377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002378 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002379 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002380 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002381 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002382 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002383
2384 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2386 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002387
2388 while( 1 )
2389 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002390 /*
2391 * First, check small factors for X and Y
2392 * before doing Miller-Rabin on any of them
2393 */
2394 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2395 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002396 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2397 == 0 &&
2398 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2399 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002400 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002401 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002402 }
2403
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002404 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002405 goto cleanup;
2406
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002407 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002408 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002409 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2410 * so up Y by 6 and X by 12.
2411 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002412 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2413 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002414 }
2415 }
2416
2417cleanup:
2418
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002419 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002420
2421 return( ret );
2422}
2423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002424#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002425
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002426#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002427
Paul Bakker23986e52011-04-24 08:57:21 +00002428#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002429
2430static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2431{
2432 { 693, 609, 21 },
2433 { 1764, 868, 28 },
2434 { 768454923, 542167814, 1 }
2435};
2436
Paul Bakker5121ce52009-01-03 21:22:43 +00002437/*
2438 * Checkup routine
2439 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002441{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002442 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002443 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002445 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2446 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002447
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002448 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002449 "EFE021C2645FD1DC586E69184AF4A31E" \
2450 "D5F53E93B5F123FA41680867BA110131" \
2451 "944FE7952E2517337780CB0DB80E61AA" \
2452 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2453
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002454 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002455 "B2E7EFD37075B9F03FF989C7C5051C20" \
2456 "34D2A323810251127E7BF8625A4F49A5" \
2457 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2458 "5B5C25763222FEFCCFC38B832366C29E" ) );
2459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002460 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002461 "0066A198186C18C10B2F5ED9B522752A" \
2462 "9830B69916E535C8F047518A889A43A5" \
2463 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002465 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002466
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002467 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002468 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2469 "9E857EA95A03512E2BAE7391688D264A" \
2470 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2471 "8001B72E848A38CAE1C65F78E56ABDEF" \
2472 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2473 "ECF677152EF804370C1A305CAF3B5BF1" \
2474 "30879B56C61DE584A0F53A2447A51E" ) );
2475
2476 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002477 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002478
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002479 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002480 {
2481 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002482 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002483
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002484 ret = 1;
2485 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002486 }
2487
2488 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002489 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002490
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002491 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002493 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002494 "256567336059E52CAE22925474705F39A94" ) );
2495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002496 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002497 "6613F26162223DF488E9CD48CC132C7A" \
2498 "0AC93C701B001B092E4E5B9F73BCD27B" \
2499 "9EE50D0657C77F374E903CDFA4C642" ) );
2500
2501 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002502 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002504 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2505 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002506 {
2507 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002508 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002509
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002510 ret = 1;
2511 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002512 }
2513
2514 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002515 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002516
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002517 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002518
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002519 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002520 "36E139AEA55215609D2816998ED020BB" \
2521 "BD96C37890F65171D948E9BC7CBAA4D9" \
2522 "325D24D6A3C12710F10A09FA08AB87" ) );
2523
2524 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002525 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002526
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002527 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002528 {
2529 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002530 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002531
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002532 ret = 1;
2533 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002534 }
2535
2536 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002537 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002538
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002539 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002540
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002541 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002542 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2543 "C3DBA76456363A10869622EAC2DD84EC" \
2544 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2545
2546 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002547 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002548
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002549 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002550 {
2551 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002552 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002553
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002554 ret = 1;
2555 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002556 }
2557
2558 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002559 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002560
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002561 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002563
Paul Bakker66d5d072014-06-17 16:39:18 +02002564 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002565 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002566 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2567 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002568
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002569 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002570
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002571 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002572 {
2573 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002574 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002575
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002576 ret = 1;
2577 goto cleanup;
2578 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002579 }
2580
2581 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002582 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002583
Paul Bakker5121ce52009-01-03 21:22:43 +00002584cleanup:
2585
2586 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002587 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002588
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002589 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2590 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002591
2592 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002593 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002594
2595 return( ret );
2596}
2597
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002598#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002599
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002600#endif /* MBEDTLS_BIGNUM_C */