blob: dfcb8193815c8e6f8fa210800e7772aedf8ff1c0 [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
949/*
950 * Compare signed values in constant time
951 */
952int mbedtls_mpi_cmp_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
953 int *ret )
954{
955 size_t i;
956 unsigned int cond, done;
957
958 if( X->n != Y->n )
959 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
960
961 /*
962 * if( X->s > 0 && Y->s < 0 )
963 * {
964 * *ret = 1;
965 * done = 1;
966 * }
967 * else if( Y->s > 0 && X->s < 0 )
968 * {
969 * *ret = -1;
970 * done = 1;
971 * }
972 */
973 unsigned int sign_X = X->s;
974 unsigned int sign_Y = Y->s;
975 cond = ( ( sign_X ^ sign_Y ) >> ( sizeof( unsigned int ) * 8 - 1 ) );
976 *ret = cond * X->s;
977 done = cond;
978
979 for( i = X->n; i > 0; i-- )
980 {
981 /*
982 * if( ( X->p[i - 1] > Y->p[i - 1] ) && !done )
983 * {
984 * done = 1;
985 * *ret = X->s;
986 * }
987 */
988 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
989 *ret |= ( cond * ( 1 - done ) ) * X->s;
990 done |= cond * ( 1 - done );
991
992 /*
993 * if( ( X->p[i - 1] < Y->p[i - 1] ) && !done )
994 * {
995 * done = 1;
996 * *ret = -X->s;
997 * }
998 */
999 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1000 *ret |= ( cond * ( 1 - done ) ) * -X->s;
1001 done |= cond * ( 1 - done );
1002
1003 }
1004
1005 return( 0 );
1006}
1007
Paul Bakker5121ce52009-01-03 21:22:43 +00001008/*
1009 * Compare signed values
1010 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001011int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001012{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001013 mbedtls_mpi Y;
1014 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001015
1016 *p = ( z < 0 ) ? -z : z;
1017 Y.s = ( z < 0 ) ? -1 : 1;
1018 Y.n = 1;
1019 Y.p = p;
1020
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001021 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001022}
1023
1024/*
1025 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1026 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001027int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001028{
Paul Bakker23986e52011-04-24 08:57:21 +00001029 int ret;
1030 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001031 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +00001032
1033 if( X == B )
1034 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001035 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001036 }
1037
1038 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001039 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001040
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001041 /*
1042 * X should always be positive as a result of unsigned additions.
1043 */
1044 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001045
Paul Bakker23986e52011-04-24 08:57:21 +00001046 for( j = B->n; j > 0; j-- )
1047 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001048 break;
1049
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001051
1052 o = B->p; p = X->p; c = 0;
1053
Janos Follath6c922682015-10-30 17:43:11 +01001054 /*
1055 * tmp is used because it might happen that p == o
1056 */
Paul Bakker23986e52011-04-24 08:57:21 +00001057 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001058 {
Janos Follath6c922682015-10-30 17:43:11 +01001059 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001060 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001061 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001062 }
1063
1064 while( c != 0 )
1065 {
1066 if( i >= X->n )
1067 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001068 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001069 p = X->p + i;
1070 }
1071
Paul Bakker2d319fd2012-09-16 21:34:26 +00001072 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001073 }
1074
1075cleanup:
1076
1077 return( ret );
1078}
1079
1080/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001081 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001082 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001083static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001084{
Paul Bakker23986e52011-04-24 08:57:21 +00001085 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001086 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001087
1088 for( i = c = 0; i < n; i++, s++, d++ )
1089 {
1090 z = ( *d < c ); *d -= c;
1091 c = ( *d < *s ) + z; *d -= *s;
1092 }
1093
1094 while( c != 0 )
1095 {
1096 z = ( *d < c ); *d -= c;
1097 c = z; i++; d++;
1098 }
1099}
1100
1101/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001102 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001103 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001104int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001105{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001106 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001107 int ret;
1108 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001110 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1111 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001113 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001114
1115 if( X == B )
1116 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001117 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001118 B = &TB;
1119 }
1120
1121 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001122 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001123
Paul Bakker1ef7a532009-06-20 10:50:55 +00001124 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001125 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001126 */
1127 X->s = 1;
1128
Paul Bakker5121ce52009-01-03 21:22:43 +00001129 ret = 0;
1130
Paul Bakker23986e52011-04-24 08:57:21 +00001131 for( n = B->n; n > 0; n-- )
1132 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001133 break;
1134
Paul Bakker23986e52011-04-24 08:57:21 +00001135 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001136
1137cleanup:
1138
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001139 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001140
1141 return( ret );
1142}
1143
1144/*
1145 * Signed addition: X = A + B
1146 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001147int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001148{
1149 int ret, s = A->s;
1150
1151 if( A->s * B->s < 0 )
1152 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001153 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001154 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001155 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001156 X->s = s;
1157 }
1158 else
1159 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001160 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001161 X->s = -s;
1162 }
1163 }
1164 else
1165 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001166 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001167 X->s = s;
1168 }
1169
1170cleanup:
1171
1172 return( ret );
1173}
1174
1175/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001176 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001177 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001178int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001179{
1180 int ret, s = A->s;
1181
1182 if( A->s * B->s > 0 )
1183 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001184 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001185 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001186 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001187 X->s = s;
1188 }
1189 else
1190 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001191 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001192 X->s = -s;
1193 }
1194 }
1195 else
1196 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001197 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001198 X->s = s;
1199 }
1200
1201cleanup:
1202
1203 return( ret );
1204}
1205
1206/*
1207 * Signed addition: X = A + b
1208 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001209int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001210{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001211 mbedtls_mpi _B;
1212 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001213
1214 p[0] = ( b < 0 ) ? -b : b;
1215 _B.s = ( b < 0 ) ? -1 : 1;
1216 _B.n = 1;
1217 _B.p = p;
1218
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001219 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001220}
1221
1222/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001223 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001224 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001225int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001226{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001227 mbedtls_mpi _B;
1228 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001229
1230 p[0] = ( b < 0 ) ? -b : b;
1231 _B.s = ( b < 0 ) ? -1 : 1;
1232 _B.n = 1;
1233 _B.p = p;
1234
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001235 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001236}
1237
1238/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001239 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001240 */
1241static
1242#if defined(__APPLE__) && defined(__arm__)
1243/*
1244 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1245 * appears to need this to prevent bad ARM code generation at -O3.
1246 */
1247__attribute__ ((noinline))
1248#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001249void 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 +00001250{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001251 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001252
1253#if defined(MULADDC_HUIT)
1254 for( ; i >= 8; i -= 8 )
1255 {
1256 MULADDC_INIT
1257 MULADDC_HUIT
1258 MULADDC_STOP
1259 }
1260
1261 for( ; i > 0; i-- )
1262 {
1263 MULADDC_INIT
1264 MULADDC_CORE
1265 MULADDC_STOP
1266 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001267#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001268 for( ; i >= 16; i -= 16 )
1269 {
1270 MULADDC_INIT
1271 MULADDC_CORE MULADDC_CORE
1272 MULADDC_CORE MULADDC_CORE
1273 MULADDC_CORE MULADDC_CORE
1274 MULADDC_CORE MULADDC_CORE
1275
1276 MULADDC_CORE MULADDC_CORE
1277 MULADDC_CORE MULADDC_CORE
1278 MULADDC_CORE MULADDC_CORE
1279 MULADDC_CORE MULADDC_CORE
1280 MULADDC_STOP
1281 }
1282
1283 for( ; i >= 8; i -= 8 )
1284 {
1285 MULADDC_INIT
1286 MULADDC_CORE MULADDC_CORE
1287 MULADDC_CORE MULADDC_CORE
1288
1289 MULADDC_CORE MULADDC_CORE
1290 MULADDC_CORE MULADDC_CORE
1291 MULADDC_STOP
1292 }
1293
1294 for( ; i > 0; i-- )
1295 {
1296 MULADDC_INIT
1297 MULADDC_CORE
1298 MULADDC_STOP
1299 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001300#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001301
1302 t++;
1303
1304 do {
1305 *d += c; c = ( *d < c ); d++;
1306 }
1307 while( c != 0 );
1308}
1309
1310/*
1311 * Baseline multiplication: X = A * B (HAC 14.12)
1312 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001313int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001314{
Paul Bakker23986e52011-04-24 08:57:21 +00001315 int ret;
1316 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001317 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001319 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001321 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1322 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001323
Paul Bakker23986e52011-04-24 08:57:21 +00001324 for( i = A->n; i > 0; i-- )
1325 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001326 break;
1327
Paul Bakker23986e52011-04-24 08:57:21 +00001328 for( j = B->n; j > 0; j-- )
1329 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001330 break;
1331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1333 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001334
Paul Bakker23986e52011-04-24 08:57:21 +00001335 for( i++; j > 0; j-- )
1336 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001337
1338 X->s = A->s * B->s;
1339
1340cleanup:
1341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001342 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001343
1344 return( ret );
1345}
1346
1347/*
1348 * Baseline multiplication: X = A * b
1349 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001350int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001351{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001352 mbedtls_mpi _B;
1353 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001354
1355 _B.s = 1;
1356 _B.n = 1;
1357 _B.p = p;
1358 p[0] = b;
1359
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001360 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001361}
1362
1363/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001364 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1365 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001366 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001367static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1368 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001369{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001370#if defined(MBEDTLS_HAVE_UDBL)
1371 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001372#else
Simon Butcher9803d072016-01-03 00:24:34 +00001373 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1374 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001375 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1376 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001377 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001378#endif
1379
Simon Butcher15b15d12015-11-26 19:35:03 +00001380 /*
1381 * Check for overflow
1382 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001383 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001384 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001385 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001386
Simon Butcherf5ba0452015-12-27 23:01:55 +00001387 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001388 }
1389
1390#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001391 dividend = (mbedtls_t_udbl) u1 << biL;
1392 dividend |= (mbedtls_t_udbl) u0;
1393 quotient = dividend / d;
1394 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1395 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1396
1397 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001398 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001399
1400 return (mbedtls_mpi_uint) quotient;
1401#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001402
1403 /*
1404 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1405 * Vol. 2 - Seminumerical Algorithms, Knuth
1406 */
1407
1408 /*
1409 * Normalize the divisor, d, and dividend, u0, u1
1410 */
1411 s = mbedtls_clz( d );
1412 d = d << s;
1413
1414 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001415 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001416 u0 = u0 << s;
1417
1418 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001419 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001420
1421 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001422 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001423
1424 /*
1425 * Find the first quotient and remainder
1426 */
1427 q1 = u1 / d1;
1428 r0 = u1 - d1 * q1;
1429
1430 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1431 {
1432 q1 -= 1;
1433 r0 += d1;
1434
1435 if ( r0 >= radix ) break;
1436 }
1437
Simon Butcherf5ba0452015-12-27 23:01:55 +00001438 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001439 q0 = rAX / d1;
1440 r0 = rAX - q0 * d1;
1441
1442 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1443 {
1444 q0 -= 1;
1445 r0 += d1;
1446
1447 if ( r0 >= radix ) break;
1448 }
1449
1450 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001451 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001452
1453 quotient = q1 * radix + q0;
1454
1455 return quotient;
1456#endif
1457}
1458
1459/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001460 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001461 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001462int 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 +00001463{
Paul Bakker23986e52011-04-24 08:57:21 +00001464 int ret;
1465 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001468 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1469 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1472 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001473
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001474 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001475 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001476 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1477 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001478 return( 0 );
1479 }
1480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001481 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1482 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001483 X.s = Y.s = 1;
1484
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001485 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1486 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1487 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1488 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001489
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001490 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001491 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001492 {
1493 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001494 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1495 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001496 }
1497 else k = 0;
1498
1499 n = X.n - 1;
1500 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001501 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001503 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001504 {
1505 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001507 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001508 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001509
1510 for( i = n; i > t ; i-- )
1511 {
1512 if( X.p[i] >= Y.p[t] )
1513 Z.p[i - t - 1] = ~0;
1514 else
1515 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001516 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1517 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001518 }
1519
1520 Z.p[i - t - 1]++;
1521 do
1522 {
1523 Z.p[i - t - 1]--;
1524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001525 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001526 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001527 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001528 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001529
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001530 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001531 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1532 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001533 T2.p[2] = X.p[i];
1534 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001535 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001536
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001537 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1538 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1539 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001540
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001541 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001542 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001543 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1544 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1545 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001546 Z.p[i - t - 1]--;
1547 }
1548 }
1549
1550 if( Q != NULL )
1551 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001552 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001553 Q->s = A->s * B->s;
1554 }
1555
1556 if( R != NULL )
1557 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001558 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001559 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001560 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001561
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001562 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001563 R->s = 1;
1564 }
1565
1566cleanup:
1567
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001568 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1569 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001570
1571 return( ret );
1572}
1573
1574/*
1575 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001576 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001577int 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 +00001578{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001579 mbedtls_mpi _B;
1580 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001581
1582 p[0] = ( b < 0 ) ? -b : b;
1583 _B.s = ( b < 0 ) ? -1 : 1;
1584 _B.n = 1;
1585 _B.p = p;
1586
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001587 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001588}
1589
1590/*
1591 * Modulo: R = A mod B
1592 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001593int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001594{
1595 int ret;
1596
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001597 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1598 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001599
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001600 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001601
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001602 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1603 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001604
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001605 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1606 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001607
1608cleanup:
1609
1610 return( ret );
1611}
1612
1613/*
1614 * Modulo: r = A mod b
1615 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001616int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001617{
Paul Bakker23986e52011-04-24 08:57:21 +00001618 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001619 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001620
1621 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001622 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001623
1624 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001625 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001626
1627 /*
1628 * handle trivial cases
1629 */
1630 if( b == 1 )
1631 {
1632 *r = 0;
1633 return( 0 );
1634 }
1635
1636 if( b == 2 )
1637 {
1638 *r = A->p[0] & 1;
1639 return( 0 );
1640 }
1641
1642 /*
1643 * general case
1644 */
Paul Bakker23986e52011-04-24 08:57:21 +00001645 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001646 {
Paul Bakker23986e52011-04-24 08:57:21 +00001647 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001648 y = ( y << biH ) | ( x >> biH );
1649 z = y / b;
1650 y -= z * b;
1651
1652 x <<= biH;
1653 y = ( y << biH ) | ( x >> biH );
1654 z = y / b;
1655 y -= z * b;
1656 }
1657
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001658 /*
1659 * If A is negative, then the current y represents a negative value.
1660 * Flipping it to the positive side.
1661 */
1662 if( A->s < 0 && y != 0 )
1663 y = b - y;
1664
Paul Bakker5121ce52009-01-03 21:22:43 +00001665 *r = y;
1666
1667 return( 0 );
1668}
1669
1670/*
1671 * Fast Montgomery initialization (thanks to Tom St Denis)
1672 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001673static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001674{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001675 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001676 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001677
1678 x = m0;
1679 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001680
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001681 for( i = biL; i >= 8; i /= 2 )
1682 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001683
1684 *mm = ~x + 1;
1685}
1686
1687/*
1688 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1689 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001690static 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 +02001691 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001692{
Paul Bakker23986e52011-04-24 08:57:21 +00001693 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001694 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001695
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001696 if( T->n < N->n + 1 || T->p == NULL )
1697 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1698
Paul Bakker5121ce52009-01-03 21:22:43 +00001699 memset( T->p, 0, T->n * ciL );
1700
1701 d = T->p;
1702 n = N->n;
1703 m = ( B->n < n ) ? B->n : n;
1704
1705 for( i = 0; i < n; i++ )
1706 {
1707 /*
1708 * T = (T + u0*B + u1*N) / 2^biL
1709 */
1710 u0 = A->p[i];
1711 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1712
1713 mpi_mul_hlp( m, B->p, d, u0 );
1714 mpi_mul_hlp( n, N->p, d, u1 );
1715
1716 *d++ = u0; d[n + 1] = 0;
1717 }
1718
Paul Bakker66d5d072014-06-17 16:39:18 +02001719 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001720
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001721 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001722 mpi_sub_hlp( n, N->p, A->p );
1723 else
1724 /* prevent timing attacks */
1725 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001726
1727 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001728}
1729
1730/*
1731 * Montgomery reduction: A = A * R^-1 mod N
1732 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001733static 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 +00001734{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001735 mbedtls_mpi_uint z = 1;
1736 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001737
Paul Bakker8ddb6452013-02-27 14:56:33 +01001738 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001739 U.p = &z;
1740
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001741 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001742}
1743
1744/*
1745 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1746 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001747int 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 +00001748{
Paul Bakker23986e52011-04-24 08:57:21 +00001749 int ret;
1750 size_t wbits, wsize, one = 1;
1751 size_t i, j, nblimbs;
1752 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001753 mbedtls_mpi_uint ei, mm, state;
1754 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001755 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001756
Hanno Becker930ec7d2018-03-09 10:48:00 +00001757 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001758 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001759
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001760 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1761 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001762
1763 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001764 * Init temps and window size
1765 */
1766 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001767 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1768 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001769 memset( W, 0, sizeof( W ) );
1770
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001771 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001772
1773 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1774 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1775
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001776#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001777 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1778 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001779#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001780
Paul Bakker5121ce52009-01-03 21:22:43 +00001781 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001782 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1783 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1784 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001785
1786 /*
Paul Bakker50546922012-05-19 08:40:49 +00001787 * Compensate for negative A (and correct at the end)
1788 */
1789 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001790 if( neg )
1791 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001792 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001793 Apos.s = 1;
1794 A = &Apos;
1795 }
1796
1797 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001798 * If 1st call, pre-compute R^2 mod N
1799 */
1800 if( _RR == NULL || _RR->p == NULL )
1801 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001802 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1803 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1804 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001805
1806 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001807 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001808 }
1809 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001810 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001811
1812 /*
1813 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1814 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001815 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1816 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001817 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001818 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001819
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001820 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001821
1822 /*
1823 * X = R^2 * R^-1 mod N = R mod N
1824 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001825 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001826 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001827
1828 if( wsize > 1 )
1829 {
1830 /*
1831 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1832 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001833 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001834
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001835 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1836 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001837
1838 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001839 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001840
Paul Bakker5121ce52009-01-03 21:22:43 +00001841 /*
1842 * W[i] = W[i - 1] * W[1]
1843 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001844 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001845 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001846 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1847 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001848
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001849 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001850 }
1851 }
1852
1853 nblimbs = E->n;
1854 bufsize = 0;
1855 nbits = 0;
1856 wbits = 0;
1857 state = 0;
1858
1859 while( 1 )
1860 {
1861 if( bufsize == 0 )
1862 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001863 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001864 break;
1865
Paul Bakker0d7702c2013-10-29 16:18:35 +01001866 nblimbs--;
1867
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001868 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001869 }
1870
1871 bufsize--;
1872
1873 ei = (E->p[nblimbs] >> bufsize) & 1;
1874
1875 /*
1876 * skip leading 0s
1877 */
1878 if( ei == 0 && state == 0 )
1879 continue;
1880
1881 if( ei == 0 && state == 1 )
1882 {
1883 /*
1884 * out of window, square X
1885 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001886 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001887 continue;
1888 }
1889
1890 /*
1891 * add ei to current window
1892 */
1893 state = 2;
1894
1895 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001896 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001897
1898 if( nbits == wsize )
1899 {
1900 /*
1901 * X = X^wsize R^-1 mod N
1902 */
1903 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001904 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001905
1906 /*
1907 * X = X * W[wbits] R^-1 mod N
1908 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001909 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001910
1911 state--;
1912 nbits = 0;
1913 wbits = 0;
1914 }
1915 }
1916
1917 /*
1918 * process the remaining bits
1919 */
1920 for( i = 0; i < nbits; i++ )
1921 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001922 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001923
1924 wbits <<= 1;
1925
Paul Bakker66d5d072014-06-17 16:39:18 +02001926 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001927 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001928 }
1929
1930 /*
1931 * X = A^E * R * R^-1 mod N = A^E mod N
1932 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001933 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001934
Hanno Beckera4af1c42017-04-18 09:07:45 +01001935 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001936 {
1937 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001938 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001939 }
1940
Paul Bakker5121ce52009-01-03 21:22:43 +00001941cleanup:
1942
Paul Bakker66d5d072014-06-17 16:39:18 +02001943 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001944 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001946 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001947
Paul Bakker75a28602014-03-31 12:08:17 +02001948 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001949 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001950
1951 return( ret );
1952}
1953
Paul Bakker5121ce52009-01-03 21:22:43 +00001954/*
1955 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1956 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001957int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001958{
Paul Bakker23986e52011-04-24 08:57:21 +00001959 int ret;
1960 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001961 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001962
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001964
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001965 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1966 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001967
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001968 lz = mbedtls_mpi_lsb( &TA );
1969 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001970
Paul Bakker66d5d072014-06-17 16:39:18 +02001971 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001972 lz = lzt;
1973
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001974 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1975 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001976
Paul Bakker5121ce52009-01-03 21:22:43 +00001977 TA.s = TB.s = 1;
1978
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001979 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001980 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001981 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1982 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001983
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001984 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001985 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001986 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1987 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001988 }
1989 else
1990 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001991 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1992 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001993 }
1994 }
1995
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001996 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1997 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001998
1999cleanup:
2000
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002001 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002002
2003 return( ret );
2004}
2005
Paul Bakker33dc46b2014-04-30 16:11:39 +02002006/*
2007 * Fill X with size bytes of random.
2008 *
2009 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002010 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002011 * deterministic, eg for tests).
2012 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002013int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002014 int (*f_rng)(void *, unsigned char *, size_t),
2015 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002016{
Paul Bakker23986e52011-04-24 08:57:21 +00002017 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002018 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02002019
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002020 if( size > MBEDTLS_MPI_MAX_SIZE )
2021 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002022
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2024 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002025
2026cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01002027 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002028 return( ret );
2029}
2030
Paul Bakker5121ce52009-01-03 21:22:43 +00002031/*
2032 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2033 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002035{
2036 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002037 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002038
Hanno Becker4bcb4912017-04-18 15:49:39 +01002039 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002040 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002041
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002042 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2043 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2044 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002045
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002047
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002048 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002049 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002050 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002051 goto cleanup;
2052 }
2053
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002054 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2055 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2056 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2057 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002058
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002059 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2060 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2061 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2062 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002063
2064 do
2065 {
2066 while( ( TU.p[0] & 1 ) == 0 )
2067 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002068 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002069
2070 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2071 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002072 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2073 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002074 }
2075
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2077 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002078 }
2079
2080 while( ( TV.p[0] & 1 ) == 0 )
2081 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002082 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002083
2084 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2085 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002086 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2087 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002088 }
2089
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002090 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2091 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002092 }
2093
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002094 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002095 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002096 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2097 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2098 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002099 }
2100 else
2101 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002102 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2103 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2104 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002105 }
2106 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002107 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002108
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002109 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2110 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002111
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002112 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2113 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002114
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002115 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002116
2117cleanup:
2118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002119 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2120 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2121 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002122
2123 return( ret );
2124}
2125
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002126#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002127
Paul Bakker5121ce52009-01-03 21:22:43 +00002128static const int small_prime[] =
2129{
2130 3, 5, 7, 11, 13, 17, 19, 23,
2131 29, 31, 37, 41, 43, 47, 53, 59,
2132 61, 67, 71, 73, 79, 83, 89, 97,
2133 101, 103, 107, 109, 113, 127, 131, 137,
2134 139, 149, 151, 157, 163, 167, 173, 179,
2135 181, 191, 193, 197, 199, 211, 223, 227,
2136 229, 233, 239, 241, 251, 257, 263, 269,
2137 271, 277, 281, 283, 293, 307, 311, 313,
2138 317, 331, 337, 347, 349, 353, 359, 367,
2139 373, 379, 383, 389, 397, 401, 409, 419,
2140 421, 431, 433, 439, 443, 449, 457, 461,
2141 463, 467, 479, 487, 491, 499, 503, 509,
2142 521, 523, 541, 547, 557, 563, 569, 571,
2143 577, 587, 593, 599, 601, 607, 613, 617,
2144 619, 631, 641, 643, 647, 653, 659, 661,
2145 673, 677, 683, 691, 701, 709, 719, 727,
2146 733, 739, 743, 751, 757, 761, 769, 773,
2147 787, 797, 809, 811, 821, 823, 827, 829,
2148 839, 853, 857, 859, 863, 877, 881, 883,
2149 887, 907, 911, 919, 929, 937, 941, 947,
2150 953, 967, 971, 977, 983, 991, 997, -103
2151};
2152
2153/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002154 * Small divisors test (X must be positive)
2155 *
2156 * Return values:
2157 * 0: no small factor (possible prime, more tests needed)
2158 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002159 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002160 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002161 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002162static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002163{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002164 int ret = 0;
2165 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002166 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002167
Paul Bakker5121ce52009-01-03 21:22:43 +00002168 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002169 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002170
2171 for( i = 0; small_prime[i] > 0; i++ )
2172 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002173 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002174 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002175
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002176 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002177
2178 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002179 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002180 }
2181
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002182cleanup:
2183 return( ret );
2184}
2185
2186/*
2187 * Miller-Rabin pseudo-primality test (HAC 4.24)
2188 */
Janos Follath72d555d2018-09-03 14:45:23 +01002189static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002190 int (*f_rng)(void *, unsigned char *, size_t),
2191 void *p_rng )
2192{
Pascal Junodb99183d2015-03-11 16:49:45 +01002193 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002194 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002195 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002196
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002197 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2198 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002199
Paul Bakker5121ce52009-01-03 21:22:43 +00002200 /*
2201 * W = |X| - 1
2202 * R = W >> lsb( W )
2203 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002204 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2205 s = mbedtls_mpi_lsb( &W );
2206 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2207 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002208
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002209 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002210
Janos Follath72d555d2018-09-03 14:45:23 +01002211 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002212 {
2213 /*
2214 * pick a random A, 1 < A < |X| - 1
2215 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002216 count = 0;
2217 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002218 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002219
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002220 j = mbedtls_mpi_bitlen( &A );
2221 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002222 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002223 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002224 }
2225
2226 if (count++ > 30) {
Jens Wiklanderb2aa9382019-01-17 13:30:57 +01002227 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2228 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002229 }
2230
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002231 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2232 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002233
2234 /*
2235 * A = A^R mod |X|
2236 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002237 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002239 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2240 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002241 continue;
2242
2243 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002244 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002245 {
2246 /*
2247 * A = A * A mod |X|
2248 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002249 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2250 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002251
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002252 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002253 break;
2254
2255 j++;
2256 }
2257
2258 /*
2259 * not prime if A != |X| - 1 or A == 1
2260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002261 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2262 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002263 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002265 break;
2266 }
2267 }
2268
2269cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002270 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2271 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002272
2273 return( ret );
2274}
2275
2276/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002277 * Pseudo-primality test: small factors, then Miller-Rabin
2278 */
Darryl Green94759f62018-10-16 15:09:19 +01002279static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002280 int (*f_rng)(void *, unsigned char *, size_t),
2281 void *p_rng )
2282{
2283 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002284 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002285
2286 XX.s = 1;
2287 XX.n = X->n;
2288 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002289
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002290 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2291 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2292 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
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, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002295 return( 0 );
2296
2297 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2298 {
2299 if( ret == 1 )
2300 return( 0 );
2301
2302 return( ret );
2303 }
2304
Janos Follath72d555d2018-09-03 14:45:23 +01002305 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2306}
2307
2308/*
2309 * Pseudo-primality test, error probability 2^-80
2310 */
2311int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2312 int (*f_rng)(void *, unsigned char *, size_t),
2313 void *p_rng )
2314{
2315 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002316}
2317
2318/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002319 * Prime number generation
2320 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002321int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002322 int (*f_rng)(void *, unsigned char *, size_t),
2323 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002324{
Paul Bakker23986e52011-04-24 08:57:21 +00002325 int ret;
2326 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002327 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002328 mbedtls_mpi_uint r;
2329 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002330
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002331 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2332 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002334 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002335
2336 n = BITS_TO_LIMBS( nbits );
2337
Janos Follath72d555d2018-09-03 14:45:23 +01002338 /*
2339 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2340 */
2341 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2342 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2343 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002345 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002347 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002348 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002349
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002350 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002351
2352 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002353
2354 if( dh_flag == 0 )
2355 {
Janos Follath72d555d2018-09-03 14:45:23 +01002356 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002357 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002358 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002359 goto cleanup;
2360
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002361 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002362 }
2363 }
2364 else
2365 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002366 /*
2367 * An necessary condition for Y and X = 2Y + 1 to be prime
2368 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2369 * Make sure it is satisfied, while keeping X = 3 mod 4
2370 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002371
2372 X->p[0] |= 2;
2373
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002374 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002375 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002377 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002378 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002379
2380 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002381 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2382 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002383
2384 while( 1 )
2385 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002386 /*
2387 * First, check small factors for X and Y
2388 * before doing Miller-Rabin on any of them
2389 */
2390 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2391 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002392 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2393 == 0 &&
2394 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2395 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002396 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002397 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002398 }
2399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002400 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002401 goto cleanup;
2402
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002403 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002404 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002405 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2406 * so up Y by 6 and X by 12.
2407 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002408 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2409 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002410 }
2411 }
2412
2413cleanup:
2414
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002415 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002416
2417 return( ret );
2418}
2419
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002420#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002421
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002422#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002423
Paul Bakker23986e52011-04-24 08:57:21 +00002424#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002425
2426static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2427{
2428 { 693, 609, 21 },
2429 { 1764, 868, 28 },
2430 { 768454923, 542167814, 1 }
2431};
2432
Paul Bakker5121ce52009-01-03 21:22:43 +00002433/*
2434 * Checkup routine
2435 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002436int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002437{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002438 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002439 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002440
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002441 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2442 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002443
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002444 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002445 "EFE021C2645FD1DC586E69184AF4A31E" \
2446 "D5F53E93B5F123FA41680867BA110131" \
2447 "944FE7952E2517337780CB0DB80E61AA" \
2448 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2449
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002450 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002451 "B2E7EFD37075B9F03FF989C7C5051C20" \
2452 "34D2A323810251127E7BF8625A4F49A5" \
2453 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2454 "5B5C25763222FEFCCFC38B832366C29E" ) );
2455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002456 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002457 "0066A198186C18C10B2F5ED9B522752A" \
2458 "9830B69916E535C8F047518A889A43A5" \
2459 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002461 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002463 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002464 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2465 "9E857EA95A03512E2BAE7391688D264A" \
2466 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2467 "8001B72E848A38CAE1C65F78E56ABDEF" \
2468 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2469 "ECF677152EF804370C1A305CAF3B5BF1" \
2470 "30879B56C61DE584A0F53A2447A51E" ) );
2471
2472 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002474
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002476 {
2477 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002478 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002479
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002480 ret = 1;
2481 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002482 }
2483
2484 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002485 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002486
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002487 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002489 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002490 "256567336059E52CAE22925474705F39A94" ) );
2491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002492 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002493 "6613F26162223DF488E9CD48CC132C7A" \
2494 "0AC93C701B001B092E4E5B9F73BCD27B" \
2495 "9EE50D0657C77F374E903CDFA4C642" ) );
2496
2497 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002498 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002499
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002500 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2501 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002502 {
2503 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002504 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002505
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002506 ret = 1;
2507 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002508 }
2509
2510 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002511 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002513 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002514
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002515 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002516 "36E139AEA55215609D2816998ED020BB" \
2517 "BD96C37890F65171D948E9BC7CBAA4D9" \
2518 "325D24D6A3C12710F10A09FA08AB87" ) );
2519
2520 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002521 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002522
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002523 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002524 {
2525 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002526 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002527
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002528 ret = 1;
2529 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002530 }
2531
2532 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002533 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002534
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002535 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002536
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002537 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002538 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2539 "C3DBA76456363A10869622EAC2DD84EC" \
2540 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2541
2542 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002543 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002544
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002545 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002546 {
2547 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002548 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002549
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002550 ret = 1;
2551 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002552 }
2553
2554 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002555 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002556
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002557 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002558 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002559
Paul Bakker66d5d072014-06-17 16:39:18 +02002560 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002561 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2563 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002564
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002565 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002566
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002567 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002568 {
2569 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002570 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002571
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002572 ret = 1;
2573 goto cleanup;
2574 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002575 }
2576
2577 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002578 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002579
Paul Bakker5121ce52009-01-03 21:22:43 +00002580cleanup:
2581
2582 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002583 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002584
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002585 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2586 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002587
2588 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002589 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002590
2591 return( ret );
2592}
2593
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002594#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002595
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002596#endif /* MBEDTLS_BIGNUM_C */