blob: e9c3867a6f9a60a2080d78b7ae54494aa20ce42f [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
563 n += 1; /* NULL termination */
564 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
922/*
923 * Compare signed values
924 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200925int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000926{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200927 mbedtls_mpi Y;
928 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000929
930 *p = ( z < 0 ) ? -z : z;
931 Y.s = ( z < 0 ) ? -1 : 1;
932 Y.n = 1;
933 Y.p = p;
934
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200935 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000936}
937
938/*
939 * Unsigned addition: X = |A| + |B| (HAC 14.7)
940 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000942{
Paul Bakker23986e52011-04-24 08:57:21 +0000943 int ret;
944 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100945 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000946
947 if( X == B )
948 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200949 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000950 }
951
952 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200953 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200954
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000955 /*
956 * X should always be positive as a result of unsigned additions.
957 */
958 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000959
Paul Bakker23986e52011-04-24 08:57:21 +0000960 for( j = B->n; j > 0; j-- )
961 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000962 break;
963
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200964 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000965
966 o = B->p; p = X->p; c = 0;
967
Janos Follath6c922682015-10-30 17:43:11 +0100968 /*
969 * tmp is used because it might happen that p == o
970 */
Paul Bakker23986e52011-04-24 08:57:21 +0000971 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000972 {
Janos Follath6c922682015-10-30 17:43:11 +0100973 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000974 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100975 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000976 }
977
978 while( c != 0 )
979 {
980 if( i >= X->n )
981 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200982 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000983 p = X->p + i;
984 }
985
Paul Bakker2d319fd2012-09-16 21:34:26 +0000986 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000987 }
988
989cleanup:
990
991 return( ret );
992}
993
994/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200995 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000996 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200997static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000998{
Paul Bakker23986e52011-04-24 08:57:21 +0000999 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001000 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001001
1002 for( i = c = 0; i < n; i++, s++, d++ )
1003 {
1004 z = ( *d < c ); *d -= c;
1005 c = ( *d < *s ) + z; *d -= *s;
1006 }
1007
1008 while( c != 0 )
1009 {
1010 z = ( *d < c ); *d -= c;
1011 c = z; i++; d++;
1012 }
1013}
1014
1015/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001016 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001017 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001018int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001019{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001020 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001021 int ret;
1022 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001023
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001024 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1025 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001026
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001027 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001028
1029 if( X == B )
1030 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001031 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001032 B = &TB;
1033 }
1034
1035 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001036 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001037
Paul Bakker1ef7a532009-06-20 10:50:55 +00001038 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001039 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001040 */
1041 X->s = 1;
1042
Paul Bakker5121ce52009-01-03 21:22:43 +00001043 ret = 0;
1044
Paul Bakker23986e52011-04-24 08:57:21 +00001045 for( n = B->n; n > 0; n-- )
1046 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001047 break;
1048
Paul Bakker23986e52011-04-24 08:57:21 +00001049 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001050
1051cleanup:
1052
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001053 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001054
1055 return( ret );
1056}
1057
1058/*
1059 * Signed addition: X = A + B
1060 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001061int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001062{
1063 int ret, s = A->s;
1064
1065 if( A->s * B->s < 0 )
1066 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001067 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001068 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001069 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001070 X->s = s;
1071 }
1072 else
1073 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001074 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001075 X->s = -s;
1076 }
1077 }
1078 else
1079 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001080 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001081 X->s = s;
1082 }
1083
1084cleanup:
1085
1086 return( ret );
1087}
1088
1089/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001090 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001091 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001092int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001093{
1094 int ret, s = A->s;
1095
1096 if( A->s * B->s > 0 )
1097 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001098 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001099 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001100 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001101 X->s = s;
1102 }
1103 else
1104 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001105 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001106 X->s = -s;
1107 }
1108 }
1109 else
1110 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001111 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001112 X->s = s;
1113 }
1114
1115cleanup:
1116
1117 return( ret );
1118}
1119
1120/*
1121 * Signed addition: X = A + b
1122 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001123int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001124{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001125 mbedtls_mpi _B;
1126 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001127
1128 p[0] = ( b < 0 ) ? -b : b;
1129 _B.s = ( b < 0 ) ? -1 : 1;
1130 _B.n = 1;
1131 _B.p = p;
1132
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001133 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001134}
1135
1136/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001137 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001138 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001139int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001140{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001141 mbedtls_mpi _B;
1142 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001143
1144 p[0] = ( b < 0 ) ? -b : b;
1145 _B.s = ( b < 0 ) ? -1 : 1;
1146 _B.n = 1;
1147 _B.p = p;
1148
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001149 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001150}
1151
1152/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001153 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001154 */
1155static
1156#if defined(__APPLE__) && defined(__arm__)
1157/*
1158 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1159 * appears to need this to prevent bad ARM code generation at -O3.
1160 */
1161__attribute__ ((noinline))
1162#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001163void 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 +00001164{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001165 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001166
1167#if defined(MULADDC_HUIT)
1168 for( ; i >= 8; i -= 8 )
1169 {
1170 MULADDC_INIT
1171 MULADDC_HUIT
1172 MULADDC_STOP
1173 }
1174
1175 for( ; i > 0; i-- )
1176 {
1177 MULADDC_INIT
1178 MULADDC_CORE
1179 MULADDC_STOP
1180 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001181#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001182 for( ; i >= 16; i -= 16 )
1183 {
1184 MULADDC_INIT
1185 MULADDC_CORE MULADDC_CORE
1186 MULADDC_CORE MULADDC_CORE
1187 MULADDC_CORE MULADDC_CORE
1188 MULADDC_CORE MULADDC_CORE
1189
1190 MULADDC_CORE MULADDC_CORE
1191 MULADDC_CORE MULADDC_CORE
1192 MULADDC_CORE MULADDC_CORE
1193 MULADDC_CORE MULADDC_CORE
1194 MULADDC_STOP
1195 }
1196
1197 for( ; i >= 8; i -= 8 )
1198 {
1199 MULADDC_INIT
1200 MULADDC_CORE MULADDC_CORE
1201 MULADDC_CORE MULADDC_CORE
1202
1203 MULADDC_CORE MULADDC_CORE
1204 MULADDC_CORE MULADDC_CORE
1205 MULADDC_STOP
1206 }
1207
1208 for( ; i > 0; i-- )
1209 {
1210 MULADDC_INIT
1211 MULADDC_CORE
1212 MULADDC_STOP
1213 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001214#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001215
1216 t++;
1217
1218 do {
1219 *d += c; c = ( *d < c ); d++;
1220 }
1221 while( c != 0 );
1222}
1223
1224/*
1225 * Baseline multiplication: X = A * B (HAC 14.12)
1226 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001227int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001228{
Paul Bakker23986e52011-04-24 08:57:21 +00001229 int ret;
1230 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001231 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001232
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001233 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001234
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001235 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1236 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001237
Paul Bakker23986e52011-04-24 08:57:21 +00001238 for( i = A->n; i > 0; i-- )
1239 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001240 break;
1241
Paul Bakker23986e52011-04-24 08:57:21 +00001242 for( j = B->n; j > 0; j-- )
1243 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001244 break;
1245
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001246 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1247 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001248
Paul Bakker23986e52011-04-24 08:57:21 +00001249 for( i++; j > 0; j-- )
1250 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001251
1252 X->s = A->s * B->s;
1253
1254cleanup:
1255
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001256 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001257
1258 return( ret );
1259}
1260
1261/*
1262 * Baseline multiplication: X = A * b
1263 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001264int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001265{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001266 mbedtls_mpi _B;
1267 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001268
1269 _B.s = 1;
1270 _B.n = 1;
1271 _B.p = p;
1272 p[0] = b;
1273
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001274 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001275}
1276
1277/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001278 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1279 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001280 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001281static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1282 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001283{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001284#if defined(MBEDTLS_HAVE_UDBL)
1285 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001286#else
Simon Butcher9803d072016-01-03 00:24:34 +00001287 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1288 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001289 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1290 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001291 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001292#endif
1293
Simon Butcher15b15d12015-11-26 19:35:03 +00001294 /*
1295 * Check for overflow
1296 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001297 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001298 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001299 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001300
Simon Butcherf5ba0452015-12-27 23:01:55 +00001301 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001302 }
1303
1304#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001305 dividend = (mbedtls_t_udbl) u1 << biL;
1306 dividend |= (mbedtls_t_udbl) u0;
1307 quotient = dividend / d;
1308 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1309 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1310
1311 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001312 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001313
1314 return (mbedtls_mpi_uint) quotient;
1315#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001316
1317 /*
1318 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1319 * Vol. 2 - Seminumerical Algorithms, Knuth
1320 */
1321
1322 /*
1323 * Normalize the divisor, d, and dividend, u0, u1
1324 */
1325 s = mbedtls_clz( d );
1326 d = d << s;
1327
1328 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001329 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001330 u0 = u0 << s;
1331
1332 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001333 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001334
1335 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001336 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001337
1338 /*
1339 * Find the first quotient and remainder
1340 */
1341 q1 = u1 / d1;
1342 r0 = u1 - d1 * q1;
1343
1344 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1345 {
1346 q1 -= 1;
1347 r0 += d1;
1348
1349 if ( r0 >= radix ) break;
1350 }
1351
Simon Butcherf5ba0452015-12-27 23:01:55 +00001352 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001353 q0 = rAX / d1;
1354 r0 = rAX - q0 * d1;
1355
1356 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1357 {
1358 q0 -= 1;
1359 r0 += d1;
1360
1361 if ( r0 >= radix ) break;
1362 }
1363
1364 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001365 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001366
1367 quotient = q1 * radix + q0;
1368
1369 return quotient;
1370#endif
1371}
1372
1373/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001374 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001375 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001376int 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 +00001377{
Paul Bakker23986e52011-04-24 08:57:21 +00001378 int ret;
1379 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001380 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001381
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001382 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1383 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001385 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1386 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001387
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001388 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001389 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1391 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001392 return( 0 );
1393 }
1394
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001395 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1396 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001397 X.s = Y.s = 1;
1398
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1400 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1401 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1402 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001403
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001404 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001405 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001406 {
1407 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001408 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1409 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001410 }
1411 else k = 0;
1412
1413 n = X.n - 1;
1414 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001415 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001416
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001417 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001418 {
1419 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001420 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001421 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001422 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001423
1424 for( i = n; i > t ; i-- )
1425 {
1426 if( X.p[i] >= Y.p[t] )
1427 Z.p[i - t - 1] = ~0;
1428 else
1429 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001430 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1431 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001432 }
1433
1434 Z.p[i - t - 1]++;
1435 do
1436 {
1437 Z.p[i - t - 1]--;
1438
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001439 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001440 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001441 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001442 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001443
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001444 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001445 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1446 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001447 T2.p[2] = X.p[i];
1448 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001449 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001451 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1452 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1453 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001455 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001456 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001457 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1458 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1459 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001460 Z.p[i - t - 1]--;
1461 }
1462 }
1463
1464 if( Q != NULL )
1465 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001467 Q->s = A->s * B->s;
1468 }
1469
1470 if( R != NULL )
1471 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001472 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001473 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001474 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001475
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001476 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001477 R->s = 1;
1478 }
1479
1480cleanup:
1481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001482 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1483 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001484
1485 return( ret );
1486}
1487
1488/*
1489 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001490 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001491int 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 +00001492{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001493 mbedtls_mpi _B;
1494 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001495
1496 p[0] = ( b < 0 ) ? -b : b;
1497 _B.s = ( b < 0 ) ? -1 : 1;
1498 _B.n = 1;
1499 _B.p = p;
1500
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001501 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001502}
1503
1504/*
1505 * Modulo: R = A mod B
1506 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001507int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001508{
1509 int ret;
1510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1512 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001514 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001515
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001516 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1517 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001518
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001519 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1520 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001521
1522cleanup:
1523
1524 return( ret );
1525}
1526
1527/*
1528 * Modulo: r = A mod b
1529 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001530int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001531{
Paul Bakker23986e52011-04-24 08:57:21 +00001532 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001533 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001534
1535 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001536 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001537
1538 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001540
1541 /*
1542 * handle trivial cases
1543 */
1544 if( b == 1 )
1545 {
1546 *r = 0;
1547 return( 0 );
1548 }
1549
1550 if( b == 2 )
1551 {
1552 *r = A->p[0] & 1;
1553 return( 0 );
1554 }
1555
1556 /*
1557 * general case
1558 */
Paul Bakker23986e52011-04-24 08:57:21 +00001559 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001560 {
Paul Bakker23986e52011-04-24 08:57:21 +00001561 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001562 y = ( y << biH ) | ( x >> biH );
1563 z = y / b;
1564 y -= z * b;
1565
1566 x <<= biH;
1567 y = ( y << biH ) | ( x >> biH );
1568 z = y / b;
1569 y -= z * b;
1570 }
1571
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001572 /*
1573 * If A is negative, then the current y represents a negative value.
1574 * Flipping it to the positive side.
1575 */
1576 if( A->s < 0 && y != 0 )
1577 y = b - y;
1578
Paul Bakker5121ce52009-01-03 21:22:43 +00001579 *r = y;
1580
1581 return( 0 );
1582}
1583
1584/*
1585 * Fast Montgomery initialization (thanks to Tom St Denis)
1586 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001587static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001588{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001589 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001590 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001591
1592 x = m0;
1593 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001594
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001595 for( i = biL; i >= 8; i /= 2 )
1596 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001597
1598 *mm = ~x + 1;
1599}
1600
1601/*
1602 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1603 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001604static 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 +02001605 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001606{
Paul Bakker23986e52011-04-24 08:57:21 +00001607 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001608 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001609
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001610 if( T->n < N->n + 1 || T->p == NULL )
1611 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1612
Paul Bakker5121ce52009-01-03 21:22:43 +00001613 memset( T->p, 0, T->n * ciL );
1614
1615 d = T->p;
1616 n = N->n;
1617 m = ( B->n < n ) ? B->n : n;
1618
1619 for( i = 0; i < n; i++ )
1620 {
1621 /*
1622 * T = (T + u0*B + u1*N) / 2^biL
1623 */
1624 u0 = A->p[i];
1625 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1626
1627 mpi_mul_hlp( m, B->p, d, u0 );
1628 mpi_mul_hlp( n, N->p, d, u1 );
1629
1630 *d++ = u0; d[n + 1] = 0;
1631 }
1632
Paul Bakker66d5d072014-06-17 16:39:18 +02001633 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001635 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001636 mpi_sub_hlp( n, N->p, A->p );
1637 else
1638 /* prevent timing attacks */
1639 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001640
1641 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001642}
1643
1644/*
1645 * Montgomery reduction: A = A * R^-1 mod N
1646 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001647static 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 +00001648{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001649 mbedtls_mpi_uint z = 1;
1650 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001651
Paul Bakker8ddb6452013-02-27 14:56:33 +01001652 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001653 U.p = &z;
1654
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001655 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001656}
1657
1658/*
1659 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1660 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661int 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 +00001662{
Paul Bakker23986e52011-04-24 08:57:21 +00001663 int ret;
1664 size_t wbits, wsize, one = 1;
1665 size_t i, j, nblimbs;
1666 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001667 mbedtls_mpi_uint ei, mm, state;
1668 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001669 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001670
Hanno Becker930ec7d2018-03-09 10:48:00 +00001671 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001672 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001673
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001674 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1675 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001676
1677 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001678 * Init temps and window size
1679 */
1680 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001681 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1682 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001683 memset( W, 0, sizeof( W ) );
1684
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001685 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001686
1687 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1688 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1689
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001690#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001691 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1692 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001693#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001694
Paul Bakker5121ce52009-01-03 21:22:43 +00001695 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001696 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1697 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1698 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001699
1700 /*
Paul Bakker50546922012-05-19 08:40:49 +00001701 * Compensate for negative A (and correct at the end)
1702 */
1703 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001704 if( neg )
1705 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001706 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001707 Apos.s = 1;
1708 A = &Apos;
1709 }
1710
1711 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001712 * If 1st call, pre-compute R^2 mod N
1713 */
1714 if( _RR == NULL || _RR->p == NULL )
1715 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001716 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1717 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1718 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001719
1720 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001721 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001722 }
1723 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001724 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001725
1726 /*
1727 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1728 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001729 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1730 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001731 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001732 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001733
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001734 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001735
1736 /*
1737 * X = R^2 * R^-1 mod N = R mod N
1738 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001739 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001740 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001741
1742 if( wsize > 1 )
1743 {
1744 /*
1745 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1746 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001747 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001748
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001749 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1750 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001751
1752 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001753 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001754
Paul Bakker5121ce52009-01-03 21:22:43 +00001755 /*
1756 * W[i] = W[i - 1] * W[1]
1757 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001758 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001759 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001760 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1761 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001762
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001763 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001764 }
1765 }
1766
1767 nblimbs = E->n;
1768 bufsize = 0;
1769 nbits = 0;
1770 wbits = 0;
1771 state = 0;
1772
1773 while( 1 )
1774 {
1775 if( bufsize == 0 )
1776 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001777 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001778 break;
1779
Paul Bakker0d7702c2013-10-29 16:18:35 +01001780 nblimbs--;
1781
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001782 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001783 }
1784
1785 bufsize--;
1786
1787 ei = (E->p[nblimbs] >> bufsize) & 1;
1788
1789 /*
1790 * skip leading 0s
1791 */
1792 if( ei == 0 && state == 0 )
1793 continue;
1794
1795 if( ei == 0 && state == 1 )
1796 {
1797 /*
1798 * out of window, square X
1799 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001800 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001801 continue;
1802 }
1803
1804 /*
1805 * add ei to current window
1806 */
1807 state = 2;
1808
1809 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001810 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001811
1812 if( nbits == wsize )
1813 {
1814 /*
1815 * X = X^wsize R^-1 mod N
1816 */
1817 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001818 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001819
1820 /*
1821 * X = X * W[wbits] R^-1 mod N
1822 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001823 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001824
1825 state--;
1826 nbits = 0;
1827 wbits = 0;
1828 }
1829 }
1830
1831 /*
1832 * process the remaining bits
1833 */
1834 for( i = 0; i < nbits; i++ )
1835 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001836 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001837
1838 wbits <<= 1;
1839
Paul Bakker66d5d072014-06-17 16:39:18 +02001840 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001841 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001842 }
1843
1844 /*
1845 * X = A^E * R * R^-1 mod N = A^E mod N
1846 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001847 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001848
Hanno Beckera4af1c42017-04-18 09:07:45 +01001849 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001850 {
1851 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001852 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001853 }
1854
Paul Bakker5121ce52009-01-03 21:22:43 +00001855cleanup:
1856
Paul Bakker66d5d072014-06-17 16:39:18 +02001857 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001858 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001859
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001860 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001861
Paul Bakker75a28602014-03-31 12:08:17 +02001862 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001863 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001864
1865 return( ret );
1866}
1867
Paul Bakker5121ce52009-01-03 21:22:43 +00001868/*
1869 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1870 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001871int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001872{
Paul Bakker23986e52011-04-24 08:57:21 +00001873 int ret;
1874 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001875 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001876
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001877 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001878
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1880 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001881
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882 lz = mbedtls_mpi_lsb( &TA );
1883 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001884
Paul Bakker66d5d072014-06-17 16:39:18 +02001885 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001886 lz = lzt;
1887
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001888 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1889 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001890
Paul Bakker5121ce52009-01-03 21:22:43 +00001891 TA.s = TB.s = 1;
1892
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001893 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001894 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001895 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1896 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001897
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001898 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001899 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001900 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1901 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001902 }
1903 else
1904 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001905 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1906 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001907 }
1908 }
1909
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001910 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1911 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001912
1913cleanup:
1914
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001915 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001916
1917 return( ret );
1918}
1919
Paul Bakker33dc46b2014-04-30 16:11:39 +02001920/*
1921 * Fill X with size bytes of random.
1922 *
1923 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001924 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001925 * deterministic, eg for tests).
1926 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001927int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001928 int (*f_rng)(void *, unsigned char *, size_t),
1929 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001930{
Paul Bakker23986e52011-04-24 08:57:21 +00001931 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001932 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001933
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001934 if( size > MBEDTLS_MPI_MAX_SIZE )
1935 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001936
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001937 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1938 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001939
1940cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01001941 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001942 return( ret );
1943}
1944
Paul Bakker5121ce52009-01-03 21:22:43 +00001945/*
1946 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1947 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001948int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001949{
1950 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001951 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001952
Hanno Becker4bcb4912017-04-18 15:49:39 +01001953 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001954 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001955
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001956 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1957 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1958 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001959
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001960 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001961
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001962 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001963 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001964 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001965 goto cleanup;
1966 }
1967
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001968 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1969 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1970 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1971 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001972
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001973 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1974 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1975 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1976 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001977
1978 do
1979 {
1980 while( ( TU.p[0] & 1 ) == 0 )
1981 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001982 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001983
1984 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1985 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001986 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1987 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001988 }
1989
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001990 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1991 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001992 }
1993
1994 while( ( TV.p[0] & 1 ) == 0 )
1995 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001996 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001997
1998 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1999 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002000 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2001 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002002 }
2003
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002004 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2005 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002006 }
2007
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002008 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002009 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002010 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2011 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2012 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002013 }
2014 else
2015 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2017 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2018 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002019 }
2020 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002021 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2024 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002025
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002026 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2027 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002028
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002030
2031cleanup:
2032
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002033 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2034 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2035 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002036
2037 return( ret );
2038}
2039
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002040#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002041
Paul Bakker5121ce52009-01-03 21:22:43 +00002042static const int small_prime[] =
2043{
2044 3, 5, 7, 11, 13, 17, 19, 23,
2045 29, 31, 37, 41, 43, 47, 53, 59,
2046 61, 67, 71, 73, 79, 83, 89, 97,
2047 101, 103, 107, 109, 113, 127, 131, 137,
2048 139, 149, 151, 157, 163, 167, 173, 179,
2049 181, 191, 193, 197, 199, 211, 223, 227,
2050 229, 233, 239, 241, 251, 257, 263, 269,
2051 271, 277, 281, 283, 293, 307, 311, 313,
2052 317, 331, 337, 347, 349, 353, 359, 367,
2053 373, 379, 383, 389, 397, 401, 409, 419,
2054 421, 431, 433, 439, 443, 449, 457, 461,
2055 463, 467, 479, 487, 491, 499, 503, 509,
2056 521, 523, 541, 547, 557, 563, 569, 571,
2057 577, 587, 593, 599, 601, 607, 613, 617,
2058 619, 631, 641, 643, 647, 653, 659, 661,
2059 673, 677, 683, 691, 701, 709, 719, 727,
2060 733, 739, 743, 751, 757, 761, 769, 773,
2061 787, 797, 809, 811, 821, 823, 827, 829,
2062 839, 853, 857, 859, 863, 877, 881, 883,
2063 887, 907, 911, 919, 929, 937, 941, 947,
2064 953, 967, 971, 977, 983, 991, 997, -103
2065};
2066
2067/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002068 * Small divisors test (X must be positive)
2069 *
2070 * Return values:
2071 * 0: no small factor (possible prime, more tests needed)
2072 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002073 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002074 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002075 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002077{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002078 int ret = 0;
2079 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002080 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002081
Paul Bakker5121ce52009-01-03 21:22:43 +00002082 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002083 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002084
2085 for( i = 0; small_prime[i] > 0; i++ )
2086 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002087 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002088 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002089
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002090 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002091
2092 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002093 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002094 }
2095
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002096cleanup:
2097 return( ret );
2098}
2099
2100/*
2101 * Miller-Rabin pseudo-primality test (HAC 4.24)
2102 */
Janos Follath72d555d2018-09-03 14:45:23 +01002103static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002104 int (*f_rng)(void *, unsigned char *, size_t),
2105 void *p_rng )
2106{
Pascal Junodb99183d2015-03-11 16:49:45 +01002107 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002108 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002109 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002111 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2112 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002113
Paul Bakker5121ce52009-01-03 21:22:43 +00002114 /*
2115 * W = |X| - 1
2116 * R = W >> lsb( W )
2117 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002118 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2119 s = mbedtls_mpi_lsb( &W );
2120 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2121 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002122
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002123 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002124
Janos Follath72d555d2018-09-03 14:45:23 +01002125 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002126 {
2127 /*
2128 * pick a random A, 1 < A < |X| - 1
2129 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002130 count = 0;
2131 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002132 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002133
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002134 j = mbedtls_mpi_bitlen( &A );
2135 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002136 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002137 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002138 }
2139
2140 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002141 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002142 }
2143
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002144 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2145 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002146
2147 /*
2148 * A = A^R mod |X|
2149 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002150 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002152 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2153 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002154 continue;
2155
2156 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002157 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002158 {
2159 /*
2160 * A = A * A mod |X|
2161 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002162 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2163 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002164
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002165 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002166 break;
2167
2168 j++;
2169 }
2170
2171 /*
2172 * not prime if A != |X| - 1 or A == 1
2173 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002174 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2175 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002176 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002178 break;
2179 }
2180 }
2181
2182cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002183 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2184 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002185
2186 return( ret );
2187}
2188
2189/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002190 * Pseudo-primality test: small factors, then Miller-Rabin
2191 */
Darryl Green94759f62018-10-16 15:09:19 +01002192static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002193 int (*f_rng)(void *, unsigned char *, size_t),
2194 void *p_rng )
2195{
2196 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002197 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002198
2199 XX.s = 1;
2200 XX.n = X->n;
2201 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002202
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002203 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2204 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2205 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002206
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002207 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002208 return( 0 );
2209
2210 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2211 {
2212 if( ret == 1 )
2213 return( 0 );
2214
2215 return( ret );
2216 }
2217
Janos Follath72d555d2018-09-03 14:45:23 +01002218 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2219}
2220
2221/*
2222 * Pseudo-primality test, error probability 2^-80
2223 */
2224int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2225 int (*f_rng)(void *, unsigned char *, size_t),
2226 void *p_rng )
2227{
2228 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002229}
2230
2231/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002232 * Prime number generation
2233 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002234int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002235 int (*f_rng)(void *, unsigned char *, size_t),
2236 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002237{
Paul Bakker23986e52011-04-24 08:57:21 +00002238 int ret;
2239 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002240 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002241 mbedtls_mpi_uint r;
2242 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002243
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002244 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2245 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002246
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002247 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002248
2249 n = BITS_TO_LIMBS( nbits );
2250
Janos Follath72d555d2018-09-03 14:45:23 +01002251 /*
2252 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2253 */
2254 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2255 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2256 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2257
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002258 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002259
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002260 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002261 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002262
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002263 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002264
2265 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002266
2267 if( dh_flag == 0 )
2268 {
Janos Follath72d555d2018-09-03 14:45:23 +01002269 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002270 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002271 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002272 goto cleanup;
2273
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002274 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002275 }
2276 }
2277 else
2278 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002279 /*
2280 * An necessary condition for Y and X = 2Y + 1 to be prime
2281 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2282 * Make sure it is satisfied, while keeping X = 3 mod 4
2283 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002284
2285 X->p[0] |= 2;
2286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002287 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002288 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002289 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002290 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002291 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002292
2293 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002294 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2295 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002296
2297 while( 1 )
2298 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002299 /*
2300 * First, check small factors for X and Y
2301 * before doing Miller-Rabin on any of them
2302 */
2303 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2304 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002305 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2306 == 0 &&
2307 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2308 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002309 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002310 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002311 }
2312
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002313 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002314 goto cleanup;
2315
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002316 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002317 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002318 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2319 * so up Y by 6 and X by 12.
2320 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002321 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2322 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002323 }
2324 }
2325
2326cleanup:
2327
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002328 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002329
2330 return( ret );
2331}
2332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002333#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002336
Paul Bakker23986e52011-04-24 08:57:21 +00002337#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002338
2339static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2340{
2341 { 693, 609, 21 },
2342 { 1764, 868, 28 },
2343 { 768454923, 542167814, 1 }
2344};
2345
Paul Bakker5121ce52009-01-03 21:22:43 +00002346/*
2347 * Checkup routine
2348 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002349int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002350{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002351 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002352 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002354 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2355 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002356
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002357 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002358 "EFE021C2645FD1DC586E69184AF4A31E" \
2359 "D5F53E93B5F123FA41680867BA110131" \
2360 "944FE7952E2517337780CB0DB80E61AA" \
2361 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2362
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002363 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002364 "B2E7EFD37075B9F03FF989C7C5051C20" \
2365 "34D2A323810251127E7BF8625A4F49A5" \
2366 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2367 "5B5C25763222FEFCCFC38B832366C29E" ) );
2368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002369 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002370 "0066A198186C18C10B2F5ED9B522752A" \
2371 "9830B69916E535C8F047518A889A43A5" \
2372 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2373
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002374 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002375
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002377 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2378 "9E857EA95A03512E2BAE7391688D264A" \
2379 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2380 "8001B72E848A38CAE1C65F78E56ABDEF" \
2381 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2382 "ECF677152EF804370C1A305CAF3B5BF1" \
2383 "30879B56C61DE584A0F53A2447A51E" ) );
2384
2385 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002386 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002387
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002388 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002389 {
2390 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002391 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002392
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002393 ret = 1;
2394 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002395 }
2396
2397 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002398 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002400 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002401
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002402 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002403 "256567336059E52CAE22925474705F39A94" ) );
2404
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002405 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002406 "6613F26162223DF488E9CD48CC132C7A" \
2407 "0AC93C701B001B092E4E5B9F73BCD27B" \
2408 "9EE50D0657C77F374E903CDFA4C642" ) );
2409
2410 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002411 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002413 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2414 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002415 {
2416 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002417 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002418
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002419 ret = 1;
2420 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002421 }
2422
2423 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002424 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002425
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002426 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002427
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002428 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002429 "36E139AEA55215609D2816998ED020BB" \
2430 "BD96C37890F65171D948E9BC7CBAA4D9" \
2431 "325D24D6A3C12710F10A09FA08AB87" ) );
2432
2433 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002435
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002436 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002437 {
2438 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002439 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002440
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002441 ret = 1;
2442 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002443 }
2444
2445 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002446 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002447
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002448 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002449
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002450 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002451 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2452 "C3DBA76456363A10869622EAC2DD84EC" \
2453 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2454
2455 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002456 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002457
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002458 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002459 {
2460 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002461 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002462
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002463 ret = 1;
2464 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002465 }
2466
2467 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002468 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002469
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002470 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002471 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002472
Paul Bakker66d5d072014-06-17 16:39:18 +02002473 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002474 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2476 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002477
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002478 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002479
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002480 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002481 {
2482 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002483 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002484
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002485 ret = 1;
2486 goto cleanup;
2487 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002488 }
2489
2490 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002491 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002492
Paul Bakker5121ce52009-01-03 21:22:43 +00002493cleanup:
2494
2495 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002496 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002497
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002498 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2499 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002500
2501 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002502 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002503
2504 return( ret );
2505}
2506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002507#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002509#endif /* MBEDTLS_BIGNUM_C */