blob: 18daea25893f239b589992e36af5eba019341c50 [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/*
503 * Helper to write the digits high-order first
504 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200505static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000506{
507 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000509
510 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200511 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
514 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000515
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
517 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000518
519 if( r < 10 )
520 *(*p)++ = (char)( r + 0x30 );
521 else
522 *(*p)++ = (char)( r + 0x37 );
523
524cleanup:
525
526 return( ret );
527}
528
529/*
530 * Export into an ASCII string
531 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100532int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
533 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000534{
Paul Bakker23986e52011-04-24 08:57:21 +0000535 int ret = 0;
536 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000537 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
540 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200541 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000542
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200543 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000544 if( radix >= 4 ) n >>= 1;
545 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000546 /*
547 * Round up the buffer length to an even value to ensure that there is
548 * enough room for hexadecimal values that can be represented in an odd
549 * number of digits.
550 */
551 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000552
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100553 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000554 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100555 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200556 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000557 }
558
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100559 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200560 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000561
562 if( X->s == -1 )
563 *p++ = '-';
564
565 if( radix == 16 )
566 {
Paul Bakker23986e52011-04-24 08:57:21 +0000567 int c;
568 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000569
Paul Bakker23986e52011-04-24 08:57:21 +0000570 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000571 {
Paul Bakker23986e52011-04-24 08:57:21 +0000572 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000573 {
Paul Bakker23986e52011-04-24 08:57:21 +0000574 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000575
Paul Bakker6c343d72014-07-10 14:36:19 +0200576 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000577 continue;
578
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000579 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000580 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000581 k = 1;
582 }
583 }
584 }
585 else
586 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200587 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000588
589 if( T.s == -1 )
590 T.s = 1;
591
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200592 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000593 }
594
595 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100596 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000597
598cleanup:
599
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200600 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000601
602 return( ret );
603}
604
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200605#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000606/*
607 * Read X from an opened file
608 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200609int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000610{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000612 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000613 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000614 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000615 * Buffer should have space for (short) label and decimal formatted MPI,
616 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000617 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200618 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000619
620 memset( s, 0, sizeof( s ) );
621 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000623
624 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000625 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200626 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000627
Hanno Beckerb2034b72017-04-26 11:46:46 +0100628 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
629 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000630
631 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100632 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000633 if( mpi_get_digit( &d, radix, *p ) != 0 )
634 break;
635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200636 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000637}
638
639/*
640 * Write X into an opened file (or stdout if fout == NULL)
641 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000643{
Paul Bakker23986e52011-04-24 08:57:21 +0000644 int ret;
645 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000646 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000647 * Buffer should have space for (short) label and decimal formatted MPI,
648 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000649 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000651
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100652 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000653
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100654 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000655
656 if( p == NULL ) p = "";
657
658 plen = strlen( p );
659 slen = strlen( s );
660 s[slen++] = '\r';
661 s[slen++] = '\n';
662
663 if( fout != NULL )
664 {
665 if( fwrite( p, 1, plen, fout ) != plen ||
666 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000668 }
669 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000671
672cleanup:
673
674 return( ret );
675}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000677
678/*
679 * Import X from unsigned binary data, big endian
680 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000682{
Paul Bakker23986e52011-04-24 08:57:21 +0000683 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100684 size_t i, j;
685 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000686
Hanno Becker073c1992017-10-17 15:17:27 +0100687 /* Ensure that target MPI has exactly the necessary number of limbs */
688 if( X->n != limbs )
689 {
690 mbedtls_mpi_free( X );
691 mbedtls_mpi_init( X );
692 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
693 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000694
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000696
Hanno Becker073c1992017-10-17 15:17:27 +0100697 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000699
700cleanup:
701
702 return( ret );
703}
704
705/*
706 * Export X into unsigned binary data, big endian
707 */
Gilles Peskine220cc172018-11-20 16:47:47 +0100708int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
709 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000710{
Gilles Peskine220cc172018-11-20 16:47:47 +0100711 size_t stored_bytes = X->n * ciL;
712 size_t bytes_to_copy;
713 unsigned char *p;
714 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000715
Gilles Peskine220cc172018-11-20 16:47:47 +0100716 if( stored_bytes < buflen )
717 {
718 /* There is enough space in the output buffer. Write initial
719 * null bytes and record the position at which to start
720 * writing the significant bytes. In this case, the execution
721 * trace of this function does not depend on the value of the
722 * number. */
723 bytes_to_copy = stored_bytes;
724 p = buf + buflen - stored_bytes;
725 memset( buf, 0, buflen - stored_bytes );
726 }
727 else
728 {
729 /* The output buffer is smaller than the allocated size of X.
730 * However X may fit if its leading bytes are zero. */
731 bytes_to_copy = buflen;
732 p = buf;
733 for( i = bytes_to_copy; i < stored_bytes; i++ )
734 {
735 if( GET_BYTE( X, i ) != 0 )
736 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
737 }
738 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000739
Gilles Peskine220cc172018-11-20 16:47:47 +0100740 for( i = 0; i < bytes_to_copy; i++ )
741 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000742
743 return( 0 );
744}
745
746/*
747 * Left-shift: X <<= count
748 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200749int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000750{
Paul Bakker23986e52011-04-24 08:57:21 +0000751 int ret;
752 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200753 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000754
755 v0 = count / (biL );
756 t1 = count & (biL - 1);
757
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200758 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000759
Paul Bakkerf9688572011-05-05 10:00:45 +0000760 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200761 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000762
763 ret = 0;
764
765 /*
766 * shift by count / limb_size
767 */
768 if( v0 > 0 )
769 {
Paul Bakker23986e52011-04-24 08:57:21 +0000770 for( i = X->n; i > v0; i-- )
771 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000772
Paul Bakker23986e52011-04-24 08:57:21 +0000773 for( ; i > 0; i-- )
774 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000775 }
776
777 /*
778 * shift by count % limb_size
779 */
780 if( t1 > 0 )
781 {
782 for( i = v0; i < X->n; i++ )
783 {
784 r1 = X->p[i] >> (biL - t1);
785 X->p[i] <<= t1;
786 X->p[i] |= r0;
787 r0 = r1;
788 }
789 }
790
791cleanup:
792
793 return( ret );
794}
795
796/*
797 * Right-shift: X >>= count
798 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200799int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000800{
Paul Bakker23986e52011-04-24 08:57:21 +0000801 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200802 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000803
804 v0 = count / biL;
805 v1 = count & (biL - 1);
806
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100807 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200808 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100809
Paul Bakker5121ce52009-01-03 21:22:43 +0000810 /*
811 * shift by count / limb_size
812 */
813 if( v0 > 0 )
814 {
815 for( i = 0; i < X->n - v0; i++ )
816 X->p[i] = X->p[i + v0];
817
818 for( ; i < X->n; i++ )
819 X->p[i] = 0;
820 }
821
822 /*
823 * shift by count % limb_size
824 */
825 if( v1 > 0 )
826 {
Paul Bakker23986e52011-04-24 08:57:21 +0000827 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000828 {
Paul Bakker23986e52011-04-24 08:57:21 +0000829 r1 = X->p[i - 1] << (biL - v1);
830 X->p[i - 1] >>= v1;
831 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000832 r0 = r1;
833 }
834 }
835
836 return( 0 );
837}
838
839/*
840 * Compare unsigned values
841 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200842int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000843{
Paul Bakker23986e52011-04-24 08:57:21 +0000844 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000845
Paul Bakker23986e52011-04-24 08:57:21 +0000846 for( i = X->n; i > 0; i-- )
847 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000848 break;
849
Paul Bakker23986e52011-04-24 08:57:21 +0000850 for( j = Y->n; j > 0; j-- )
851 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000852 break;
853
Paul Bakker23986e52011-04-24 08:57:21 +0000854 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000855 return( 0 );
856
857 if( i > j ) return( 1 );
858 if( j > i ) return( -1 );
859
Paul Bakker23986e52011-04-24 08:57:21 +0000860 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000861 {
Paul Bakker23986e52011-04-24 08:57:21 +0000862 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
863 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000864 }
865
866 return( 0 );
867}
868
869/*
870 * Compare signed values
871 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200872int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000873{
Paul Bakker23986e52011-04-24 08:57:21 +0000874 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000875
Paul Bakker23986e52011-04-24 08:57:21 +0000876 for( i = X->n; i > 0; i-- )
877 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000878 break;
879
Paul Bakker23986e52011-04-24 08:57:21 +0000880 for( j = Y->n; j > 0; j-- )
881 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000882 break;
883
Paul Bakker23986e52011-04-24 08:57:21 +0000884 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000885 return( 0 );
886
887 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000888 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000889
890 if( X->s > 0 && Y->s < 0 ) return( 1 );
891 if( Y->s > 0 && X->s < 0 ) return( -1 );
892
Paul Bakker23986e52011-04-24 08:57:21 +0000893 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000894 {
Paul Bakker23986e52011-04-24 08:57:21 +0000895 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
896 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000897 }
898
899 return( 0 );
900}
901
902/*
903 * Compare signed values
904 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200905int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000906{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200907 mbedtls_mpi Y;
908 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000909
910 *p = ( z < 0 ) ? -z : z;
911 Y.s = ( z < 0 ) ? -1 : 1;
912 Y.n = 1;
913 Y.p = p;
914
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200915 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000916}
917
918/*
919 * Unsigned addition: X = |A| + |B| (HAC 14.7)
920 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200921int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000922{
Paul Bakker23986e52011-04-24 08:57:21 +0000923 int ret;
924 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100925 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000926
927 if( X == B )
928 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200929 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000930 }
931
932 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200933 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200934
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000935 /*
936 * X should always be positive as a result of unsigned additions.
937 */
938 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000939
Paul Bakker23986e52011-04-24 08:57:21 +0000940 for( j = B->n; j > 0; j-- )
941 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000942 break;
943
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200944 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000945
946 o = B->p; p = X->p; c = 0;
947
Janos Follath6c922682015-10-30 17:43:11 +0100948 /*
949 * tmp is used because it might happen that p == o
950 */
Paul Bakker23986e52011-04-24 08:57:21 +0000951 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000952 {
Janos Follath6c922682015-10-30 17:43:11 +0100953 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000954 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100955 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000956 }
957
958 while( c != 0 )
959 {
960 if( i >= X->n )
961 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200962 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000963 p = X->p + i;
964 }
965
Paul Bakker2d319fd2012-09-16 21:34:26 +0000966 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000967 }
968
969cleanup:
970
971 return( ret );
972}
973
974/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200975 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000976 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000978{
Paul Bakker23986e52011-04-24 08:57:21 +0000979 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200980 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000981
982 for( i = c = 0; i < n; i++, s++, d++ )
983 {
984 z = ( *d < c ); *d -= c;
985 c = ( *d < *s ) + z; *d -= *s;
986 }
987
988 while( c != 0 )
989 {
990 z = ( *d < c ); *d -= c;
991 c = z; i++; d++;
992 }
993}
994
995/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100996 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000997 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200998int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000999{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001000 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001001 int ret;
1002 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001003
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001004 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1005 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001006
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001007 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001008
1009 if( X == B )
1010 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001011 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001012 B = &TB;
1013 }
1014
1015 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001017
Paul Bakker1ef7a532009-06-20 10:50:55 +00001018 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001019 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001020 */
1021 X->s = 1;
1022
Paul Bakker5121ce52009-01-03 21:22:43 +00001023 ret = 0;
1024
Paul Bakker23986e52011-04-24 08:57:21 +00001025 for( n = B->n; n > 0; n-- )
1026 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001027 break;
1028
Paul Bakker23986e52011-04-24 08:57:21 +00001029 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001030
1031cleanup:
1032
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001033 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001034
1035 return( ret );
1036}
1037
1038/*
1039 * Signed addition: X = A + B
1040 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001041int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001042{
1043 int ret, s = A->s;
1044
1045 if( A->s * B->s < 0 )
1046 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001047 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001048 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001049 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001050 X->s = s;
1051 }
1052 else
1053 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001054 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001055 X->s = -s;
1056 }
1057 }
1058 else
1059 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001060 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001061 X->s = s;
1062 }
1063
1064cleanup:
1065
1066 return( ret );
1067}
1068
1069/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001070 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001071 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001072int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001073{
1074 int ret, s = A->s;
1075
1076 if( A->s * B->s > 0 )
1077 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001078 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001079 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001080 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001081 X->s = s;
1082 }
1083 else
1084 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001085 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001086 X->s = -s;
1087 }
1088 }
1089 else
1090 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001091 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001092 X->s = s;
1093 }
1094
1095cleanup:
1096
1097 return( ret );
1098}
1099
1100/*
1101 * Signed addition: X = A + b
1102 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001103int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001104{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001105 mbedtls_mpi _B;
1106 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001107
1108 p[0] = ( b < 0 ) ? -b : b;
1109 _B.s = ( b < 0 ) ? -1 : 1;
1110 _B.n = 1;
1111 _B.p = p;
1112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001113 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001114}
1115
1116/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001117 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001118 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001119int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001120{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001121 mbedtls_mpi _B;
1122 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001123
1124 p[0] = ( b < 0 ) ? -b : b;
1125 _B.s = ( b < 0 ) ? -1 : 1;
1126 _B.n = 1;
1127 _B.p = p;
1128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001129 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001130}
1131
1132/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001133 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001134 */
1135static
1136#if defined(__APPLE__) && defined(__arm__)
1137/*
1138 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1139 * appears to need this to prevent bad ARM code generation at -O3.
1140 */
1141__attribute__ ((noinline))
1142#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001143void 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 +00001144{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001145 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001146
1147#if defined(MULADDC_HUIT)
1148 for( ; i >= 8; i -= 8 )
1149 {
1150 MULADDC_INIT
1151 MULADDC_HUIT
1152 MULADDC_STOP
1153 }
1154
1155 for( ; i > 0; i-- )
1156 {
1157 MULADDC_INIT
1158 MULADDC_CORE
1159 MULADDC_STOP
1160 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001161#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001162 for( ; i >= 16; i -= 16 )
1163 {
1164 MULADDC_INIT
1165 MULADDC_CORE MULADDC_CORE
1166 MULADDC_CORE MULADDC_CORE
1167 MULADDC_CORE MULADDC_CORE
1168 MULADDC_CORE MULADDC_CORE
1169
1170 MULADDC_CORE MULADDC_CORE
1171 MULADDC_CORE MULADDC_CORE
1172 MULADDC_CORE MULADDC_CORE
1173 MULADDC_CORE MULADDC_CORE
1174 MULADDC_STOP
1175 }
1176
1177 for( ; i >= 8; i -= 8 )
1178 {
1179 MULADDC_INIT
1180 MULADDC_CORE MULADDC_CORE
1181 MULADDC_CORE MULADDC_CORE
1182
1183 MULADDC_CORE MULADDC_CORE
1184 MULADDC_CORE MULADDC_CORE
1185 MULADDC_STOP
1186 }
1187
1188 for( ; i > 0; i-- )
1189 {
1190 MULADDC_INIT
1191 MULADDC_CORE
1192 MULADDC_STOP
1193 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001194#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001195
1196 t++;
1197
1198 do {
1199 *d += c; c = ( *d < c ); d++;
1200 }
1201 while( c != 0 );
1202}
1203
1204/*
1205 * Baseline multiplication: X = A * B (HAC 14.12)
1206 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001207int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001208{
Paul Bakker23986e52011-04-24 08:57:21 +00001209 int ret;
1210 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001211 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001212
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001213 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001215 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1216 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001217
Paul Bakker23986e52011-04-24 08:57:21 +00001218 for( i = A->n; i > 0; i-- )
1219 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001220 break;
1221
Paul Bakker23986e52011-04-24 08:57:21 +00001222 for( j = B->n; j > 0; j-- )
1223 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001224 break;
1225
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001226 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1227 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001228
Paul Bakker23986e52011-04-24 08:57:21 +00001229 for( i++; j > 0; j-- )
1230 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001231
1232 X->s = A->s * B->s;
1233
1234cleanup:
1235
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001236 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001237
1238 return( ret );
1239}
1240
1241/*
1242 * Baseline multiplication: X = A * b
1243 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001244int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001245{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001246 mbedtls_mpi _B;
1247 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001248
1249 _B.s = 1;
1250 _B.n = 1;
1251 _B.p = p;
1252 p[0] = b;
1253
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001254 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001255}
1256
1257/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001258 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1259 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001260 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001261static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1262 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001263{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001264#if defined(MBEDTLS_HAVE_UDBL)
1265 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001266#else
Simon Butcher9803d072016-01-03 00:24:34 +00001267 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1268 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001269 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1270 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001271 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001272#endif
1273
Simon Butcher15b15d12015-11-26 19:35:03 +00001274 /*
1275 * Check for overflow
1276 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001277 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001278 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001279 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001280
Simon Butcherf5ba0452015-12-27 23:01:55 +00001281 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001282 }
1283
1284#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001285 dividend = (mbedtls_t_udbl) u1 << biL;
1286 dividend |= (mbedtls_t_udbl) u0;
1287 quotient = dividend / d;
1288 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1289 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1290
1291 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001292 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001293
1294 return (mbedtls_mpi_uint) quotient;
1295#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001296
1297 /*
1298 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1299 * Vol. 2 - Seminumerical Algorithms, Knuth
1300 */
1301
1302 /*
1303 * Normalize the divisor, d, and dividend, u0, u1
1304 */
1305 s = mbedtls_clz( d );
1306 d = d << s;
1307
1308 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001309 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001310 u0 = u0 << s;
1311
1312 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001313 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001314
1315 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001316 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001317
1318 /*
1319 * Find the first quotient and remainder
1320 */
1321 q1 = u1 / d1;
1322 r0 = u1 - d1 * q1;
1323
1324 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1325 {
1326 q1 -= 1;
1327 r0 += d1;
1328
1329 if ( r0 >= radix ) break;
1330 }
1331
Simon Butcherf5ba0452015-12-27 23:01:55 +00001332 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001333 q0 = rAX / d1;
1334 r0 = rAX - q0 * d1;
1335
1336 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1337 {
1338 q0 -= 1;
1339 r0 += d1;
1340
1341 if ( r0 >= radix ) break;
1342 }
1343
1344 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001345 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001346
1347 quotient = q1 * radix + q0;
1348
1349 return quotient;
1350#endif
1351}
1352
1353/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001354 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001355 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001356int 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 +00001357{
Paul Bakker23986e52011-04-24 08:57:21 +00001358 int ret;
1359 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001360 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001361
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001362 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1363 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001364
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1366 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001367
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001368 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001369 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001370 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1371 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001372 return( 0 );
1373 }
1374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001375 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1376 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001377 X.s = Y.s = 1;
1378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001379 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1380 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1381 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1382 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001383
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001384 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001385 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001386 {
1387 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001388 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1389 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001390 }
1391 else k = 0;
1392
1393 n = X.n - 1;
1394 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001395 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001397 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001398 {
1399 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001401 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001402 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001403
1404 for( i = n; i > t ; i-- )
1405 {
1406 if( X.p[i] >= Y.p[t] )
1407 Z.p[i - t - 1] = ~0;
1408 else
1409 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001410 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1411 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001412 }
1413
1414 Z.p[i - t - 1]++;
1415 do
1416 {
1417 Z.p[i - t - 1]--;
1418
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001419 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001420 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001421 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001422 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001424 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001425 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1426 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001427 T2.p[2] = X.p[i];
1428 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001429 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001431 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1432 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1433 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001434
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001435 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001436 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001437 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1438 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1439 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001440 Z.p[i - t - 1]--;
1441 }
1442 }
1443
1444 if( Q != NULL )
1445 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001446 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001447 Q->s = A->s * B->s;
1448 }
1449
1450 if( R != NULL )
1451 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001452 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001453 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001454 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001456 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001457 R->s = 1;
1458 }
1459
1460cleanup:
1461
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001462 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1463 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001464
1465 return( ret );
1466}
1467
1468/*
1469 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001470 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471int 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 +00001472{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001473 mbedtls_mpi _B;
1474 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001475
1476 p[0] = ( b < 0 ) ? -b : b;
1477 _B.s = ( b < 0 ) ? -1 : 1;
1478 _B.n = 1;
1479 _B.p = p;
1480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001481 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001482}
1483
1484/*
1485 * Modulo: R = A mod B
1486 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001487int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001488{
1489 int ret;
1490
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001491 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1492 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001493
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001494 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001496 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1497 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001499 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1500 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001501
1502cleanup:
1503
1504 return( ret );
1505}
1506
1507/*
1508 * Modulo: r = A mod b
1509 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001510int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001511{
Paul Bakker23986e52011-04-24 08:57:21 +00001512 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001513 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001514
1515 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001516 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001517
1518 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001519 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001520
1521 /*
1522 * handle trivial cases
1523 */
1524 if( b == 1 )
1525 {
1526 *r = 0;
1527 return( 0 );
1528 }
1529
1530 if( b == 2 )
1531 {
1532 *r = A->p[0] & 1;
1533 return( 0 );
1534 }
1535
1536 /*
1537 * general case
1538 */
Paul Bakker23986e52011-04-24 08:57:21 +00001539 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001540 {
Paul Bakker23986e52011-04-24 08:57:21 +00001541 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001542 y = ( y << biH ) | ( x >> biH );
1543 z = y / b;
1544 y -= z * b;
1545
1546 x <<= biH;
1547 y = ( y << biH ) | ( x >> biH );
1548 z = y / b;
1549 y -= z * b;
1550 }
1551
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001552 /*
1553 * If A is negative, then the current y represents a negative value.
1554 * Flipping it to the positive side.
1555 */
1556 if( A->s < 0 && y != 0 )
1557 y = b - y;
1558
Paul Bakker5121ce52009-01-03 21:22:43 +00001559 *r = y;
1560
1561 return( 0 );
1562}
1563
1564/*
1565 * Fast Montgomery initialization (thanks to Tom St Denis)
1566 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001567static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001568{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001569 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001570 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001571
1572 x = m0;
1573 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001574
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001575 for( i = biL; i >= 8; i /= 2 )
1576 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001577
1578 *mm = ~x + 1;
1579}
1580
1581/*
1582 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1583 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001584static 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 +02001585 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001586{
Paul Bakker23986e52011-04-24 08:57:21 +00001587 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001588 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001589
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001590 if( T->n < N->n + 1 || T->p == NULL )
1591 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1592
Paul Bakker5121ce52009-01-03 21:22:43 +00001593 memset( T->p, 0, T->n * ciL );
1594
1595 d = T->p;
1596 n = N->n;
1597 m = ( B->n < n ) ? B->n : n;
1598
1599 for( i = 0; i < n; i++ )
1600 {
1601 /*
1602 * T = (T + u0*B + u1*N) / 2^biL
1603 */
1604 u0 = A->p[i];
1605 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1606
1607 mpi_mul_hlp( m, B->p, d, u0 );
1608 mpi_mul_hlp( n, N->p, d, u1 );
1609
1610 *d++ = u0; d[n + 1] = 0;
1611 }
1612
Paul Bakker66d5d072014-06-17 16:39:18 +02001613 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001615 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001616 mpi_sub_hlp( n, N->p, A->p );
1617 else
1618 /* prevent timing attacks */
1619 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001620
1621 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001622}
1623
1624/*
1625 * Montgomery reduction: A = A * R^-1 mod N
1626 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001627static 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 +00001628{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001629 mbedtls_mpi_uint z = 1;
1630 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001631
Paul Bakker8ddb6452013-02-27 14:56:33 +01001632 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001633 U.p = &z;
1634
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001635 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001636}
1637
1638/*
1639 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1640 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001641int 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 +00001642{
Paul Bakker23986e52011-04-24 08:57:21 +00001643 int ret;
1644 size_t wbits, wsize, one = 1;
1645 size_t i, j, nblimbs;
1646 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001647 mbedtls_mpi_uint ei, mm, state;
1648 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001649 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001650
Hanno Becker930ec7d2018-03-09 10:48:00 +00001651 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001652 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001653
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001654 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1655 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001656
1657 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001658 * Init temps and window size
1659 */
1660 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1662 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001663 memset( W, 0, sizeof( W ) );
1664
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001665 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001666
1667 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1668 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1669
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001670 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1671 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001672
Paul Bakker5121ce52009-01-03 21:22:43 +00001673 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001674 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1675 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1676 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001677
1678 /*
Paul Bakker50546922012-05-19 08:40:49 +00001679 * Compensate for negative A (and correct at the end)
1680 */
1681 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001682 if( neg )
1683 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001684 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001685 Apos.s = 1;
1686 A = &Apos;
1687 }
1688
1689 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001690 * If 1st call, pre-compute R^2 mod N
1691 */
1692 if( _RR == NULL || _RR->p == NULL )
1693 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001694 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1695 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1696 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001697
1698 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001699 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001700 }
1701 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001702 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001703
1704 /*
1705 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1706 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001707 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1708 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001709 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001710 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001711
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001712 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001713
1714 /*
1715 * X = R^2 * R^-1 mod N = R mod N
1716 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001717 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001718 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001719
1720 if( wsize > 1 )
1721 {
1722 /*
1723 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1724 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001725 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001726
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001727 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1728 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001729
1730 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001731 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001732
Paul Bakker5121ce52009-01-03 21:22:43 +00001733 /*
1734 * W[i] = W[i - 1] * W[1]
1735 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001736 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001737 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001738 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1739 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001740
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001741 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001742 }
1743 }
1744
1745 nblimbs = E->n;
1746 bufsize = 0;
1747 nbits = 0;
1748 wbits = 0;
1749 state = 0;
1750
1751 while( 1 )
1752 {
1753 if( bufsize == 0 )
1754 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001755 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001756 break;
1757
Paul Bakker0d7702c2013-10-29 16:18:35 +01001758 nblimbs--;
1759
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001760 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001761 }
1762
1763 bufsize--;
1764
1765 ei = (E->p[nblimbs] >> bufsize) & 1;
1766
1767 /*
1768 * skip leading 0s
1769 */
1770 if( ei == 0 && state == 0 )
1771 continue;
1772
1773 if( ei == 0 && state == 1 )
1774 {
1775 /*
1776 * out of window, square X
1777 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001778 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001779 continue;
1780 }
1781
1782 /*
1783 * add ei to current window
1784 */
1785 state = 2;
1786
1787 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001788 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001789
1790 if( nbits == wsize )
1791 {
1792 /*
1793 * X = X^wsize R^-1 mod N
1794 */
1795 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001796 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001797
1798 /*
1799 * X = X * W[wbits] R^-1 mod N
1800 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001801 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001802
1803 state--;
1804 nbits = 0;
1805 wbits = 0;
1806 }
1807 }
1808
1809 /*
1810 * process the remaining bits
1811 */
1812 for( i = 0; i < nbits; i++ )
1813 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001814 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001815
1816 wbits <<= 1;
1817
Paul Bakker66d5d072014-06-17 16:39:18 +02001818 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001819 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001820 }
1821
1822 /*
1823 * X = A^E * R * R^-1 mod N = A^E mod N
1824 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001825 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001826
Hanno Beckera4af1c42017-04-18 09:07:45 +01001827 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001828 {
1829 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001831 }
1832
Paul Bakker5121ce52009-01-03 21:22:43 +00001833cleanup:
1834
Paul Bakker66d5d072014-06-17 16:39:18 +02001835 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001836 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001837
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001838 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001839
Paul Bakker75a28602014-03-31 12:08:17 +02001840 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001841 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001842
1843 return( ret );
1844}
1845
Paul Bakker5121ce52009-01-03 21:22:43 +00001846/*
1847 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1848 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001849int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001850{
Paul Bakker23986e52011-04-24 08:57:21 +00001851 int ret;
1852 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001853 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001854
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001855 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001856
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001857 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1858 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001859
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001860 lz = mbedtls_mpi_lsb( &TA );
1861 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001862
Paul Bakker66d5d072014-06-17 16:39:18 +02001863 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001864 lz = lzt;
1865
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001866 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1867 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001868
Paul Bakker5121ce52009-01-03 21:22:43 +00001869 TA.s = TB.s = 1;
1870
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001871 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001872 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001873 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1874 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001875
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001876 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001877 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001878 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1879 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001880 }
1881 else
1882 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001883 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1884 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001885 }
1886 }
1887
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001888 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1889 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001890
1891cleanup:
1892
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001893 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001894
1895 return( ret );
1896}
1897
Paul Bakker33dc46b2014-04-30 16:11:39 +02001898/*
1899 * Fill X with size bytes of random.
1900 *
1901 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001902 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001903 * deterministic, eg for tests).
1904 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001905int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001906 int (*f_rng)(void *, unsigned char *, size_t),
1907 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001908{
Paul Bakker23986e52011-04-24 08:57:21 +00001909 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001910 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001911
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001912 if( size > MBEDTLS_MPI_MAX_SIZE )
1913 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001914
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001915 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1916 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001917
1918cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01001919 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001920 return( ret );
1921}
1922
Paul Bakker5121ce52009-01-03 21:22:43 +00001923/*
1924 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1925 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001926int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001927{
1928 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001930
Hanno Becker4bcb4912017-04-18 15:49:39 +01001931 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001932 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001933
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001934 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1935 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1936 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001937
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001938 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001939
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001940 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001941 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001942 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001943 goto cleanup;
1944 }
1945
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001946 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1947 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1948 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1949 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001950
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001951 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1952 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1953 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1954 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001955
1956 do
1957 {
1958 while( ( TU.p[0] & 1 ) == 0 )
1959 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001960 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001961
1962 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1963 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001964 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1965 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001966 }
1967
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001968 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1969 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001970 }
1971
1972 while( ( TV.p[0] & 1 ) == 0 )
1973 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001974 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001975
1976 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1977 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001978 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1979 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001980 }
1981
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001982 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1983 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001984 }
1985
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001986 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001987 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1989 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1990 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001991 }
1992 else
1993 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001994 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1995 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1996 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001997 }
1998 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001999 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002000
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002001 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2002 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002003
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002004 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2005 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002006
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002007 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002008
2009cleanup:
2010
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002011 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2012 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2013 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002014
2015 return( ret );
2016}
2017
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002018#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002019
Paul Bakker5121ce52009-01-03 21:22:43 +00002020static const int small_prime[] =
2021{
2022 3, 5, 7, 11, 13, 17, 19, 23,
2023 29, 31, 37, 41, 43, 47, 53, 59,
2024 61, 67, 71, 73, 79, 83, 89, 97,
2025 101, 103, 107, 109, 113, 127, 131, 137,
2026 139, 149, 151, 157, 163, 167, 173, 179,
2027 181, 191, 193, 197, 199, 211, 223, 227,
2028 229, 233, 239, 241, 251, 257, 263, 269,
2029 271, 277, 281, 283, 293, 307, 311, 313,
2030 317, 331, 337, 347, 349, 353, 359, 367,
2031 373, 379, 383, 389, 397, 401, 409, 419,
2032 421, 431, 433, 439, 443, 449, 457, 461,
2033 463, 467, 479, 487, 491, 499, 503, 509,
2034 521, 523, 541, 547, 557, 563, 569, 571,
2035 577, 587, 593, 599, 601, 607, 613, 617,
2036 619, 631, 641, 643, 647, 653, 659, 661,
2037 673, 677, 683, 691, 701, 709, 719, 727,
2038 733, 739, 743, 751, 757, 761, 769, 773,
2039 787, 797, 809, 811, 821, 823, 827, 829,
2040 839, 853, 857, 859, 863, 877, 881, 883,
2041 887, 907, 911, 919, 929, 937, 941, 947,
2042 953, 967, 971, 977, 983, 991, 997, -103
2043};
2044
2045/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002046 * Small divisors test (X must be positive)
2047 *
2048 * Return values:
2049 * 0: no small factor (possible prime, more tests needed)
2050 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002051 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002052 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002053 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002054static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002055{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002056 int ret = 0;
2057 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002059
Paul Bakker5121ce52009-01-03 21:22:43 +00002060 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002061 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002062
2063 for( i = 0; small_prime[i] > 0; i++ )
2064 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002065 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002066 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002067
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002068 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002069
2070 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002071 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002072 }
2073
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002074cleanup:
2075 return( ret );
2076}
2077
2078/*
2079 * Miller-Rabin pseudo-primality test (HAC 4.24)
2080 */
Janos Follath72d555d2018-09-03 14:45:23 +01002081static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002082 int (*f_rng)(void *, unsigned char *, size_t),
2083 void *p_rng )
2084{
Pascal Junodb99183d2015-03-11 16:49:45 +01002085 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002086 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002087 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002088
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002089 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2090 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002091
Paul Bakker5121ce52009-01-03 21:22:43 +00002092 /*
2093 * W = |X| - 1
2094 * R = W >> lsb( W )
2095 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002096 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2097 s = mbedtls_mpi_lsb( &W );
2098 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2099 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002100
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002101 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002102
Janos Follath72d555d2018-09-03 14:45:23 +01002103 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002104 {
2105 /*
2106 * pick a random A, 1 < A < |X| - 1
2107 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002108 count = 0;
2109 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002110 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002111
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002112 j = mbedtls_mpi_bitlen( &A );
2113 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002114 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002115 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002116 }
2117
2118 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002119 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002120 }
2121
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002122 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2123 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002124
2125 /*
2126 * A = A^R mod |X|
2127 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002128 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002129
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002130 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2131 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002132 continue;
2133
2134 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002135 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002136 {
2137 /*
2138 * A = A * A mod |X|
2139 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002140 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2141 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002142
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002143 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002144 break;
2145
2146 j++;
2147 }
2148
2149 /*
2150 * not prime if A != |X| - 1 or A == 1
2151 */
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 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002155 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002156 break;
2157 }
2158 }
2159
2160cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002161 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2162 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002163
2164 return( ret );
2165}
2166
2167/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002168 * Pseudo-primality test: small factors, then Miller-Rabin
2169 */
Darryl Green94759f62018-10-16 15:09:19 +01002170static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002171 int (*f_rng)(void *, unsigned char *, size_t),
2172 void *p_rng )
2173{
2174 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002175 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002176
2177 XX.s = 1;
2178 XX.n = X->n;
2179 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002181 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2182 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2183 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002185 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002186 return( 0 );
2187
2188 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2189 {
2190 if( ret == 1 )
2191 return( 0 );
2192
2193 return( ret );
2194 }
2195
Janos Follath72d555d2018-09-03 14:45:23 +01002196 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2197}
2198
2199/*
2200 * Pseudo-primality test, error probability 2^-80
2201 */
2202int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2203 int (*f_rng)(void *, unsigned char *, size_t),
2204 void *p_rng )
2205{
2206 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002207}
2208
2209/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002210 * Prime number generation
2211 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002212int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002213 int (*f_rng)(void *, unsigned char *, size_t),
2214 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002215{
Paul Bakker23986e52011-04-24 08:57:21 +00002216 int ret;
2217 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002218 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002219 mbedtls_mpi_uint r;
2220 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002222 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2223 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002224
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002225 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002226
2227 n = BITS_TO_LIMBS( nbits );
2228
Janos Follath72d555d2018-09-03 14:45:23 +01002229 /*
2230 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2231 */
2232 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2233 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2234 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2235
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002236 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002237
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002238 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002239 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002240
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002241 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002242
2243 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002244
2245 if( dh_flag == 0 )
2246 {
Janos Follath72d555d2018-09-03 14:45:23 +01002247 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002248 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002249 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002250 goto cleanup;
2251
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002252 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002253 }
2254 }
2255 else
2256 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002257 /*
2258 * An necessary condition for Y and X = 2Y + 1 to be prime
2259 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2260 * Make sure it is satisfied, while keeping X = 3 mod 4
2261 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002262
2263 X->p[0] |= 2;
2264
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002265 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002266 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002267 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002268 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002269 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002270
2271 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2273 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002274
2275 while( 1 )
2276 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002277 /*
2278 * First, check small factors for X and Y
2279 * before doing Miller-Rabin on any of them
2280 */
2281 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2282 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002283 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2284 == 0 &&
2285 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2286 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002287 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002288 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002289 }
2290
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002291 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002292 goto cleanup;
2293
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002294 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002295 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002296 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2297 * so up Y by 6 and X by 12.
2298 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2300 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002301 }
2302 }
2303
2304cleanup:
2305
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002306 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002307
2308 return( ret );
2309}
2310
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002311#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002312
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002313#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002314
Paul Bakker23986e52011-04-24 08:57:21 +00002315#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002316
2317static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2318{
2319 { 693, 609, 21 },
2320 { 1764, 868, 28 },
2321 { 768454923, 542167814, 1 }
2322};
2323
Paul Bakker5121ce52009-01-03 21:22:43 +00002324/*
2325 * Checkup routine
2326 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002327int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002328{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002329 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002332 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2333 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002336 "EFE021C2645FD1DC586E69184AF4A31E" \
2337 "D5F53E93B5F123FA41680867BA110131" \
2338 "944FE7952E2517337780CB0DB80E61AA" \
2339 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002342 "B2E7EFD37075B9F03FF989C7C5051C20" \
2343 "34D2A323810251127E7BF8625A4F49A5" \
2344 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2345 "5B5C25763222FEFCCFC38B832366C29E" ) );
2346
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002348 "0066A198186C18C10B2F5ED9B522752A" \
2349 "9830B69916E535C8F047518A889A43A5" \
2350 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2351
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002352 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002354 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002355 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2356 "9E857EA95A03512E2BAE7391688D264A" \
2357 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2358 "8001B72E848A38CAE1C65F78E56ABDEF" \
2359 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2360 "ECF677152EF804370C1A305CAF3B5BF1" \
2361 "30879B56C61DE584A0F53A2447A51E" ) );
2362
2363 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002364 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002366 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002367 {
2368 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002369 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002370
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002371 ret = 1;
2372 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002373 }
2374
2375 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002378 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002379
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002380 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002381 "256567336059E52CAE22925474705F39A94" ) );
2382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002384 "6613F26162223DF488E9CD48CC132C7A" \
2385 "0AC93C701B001B092E4E5B9F73BCD27B" \
2386 "9EE50D0657C77F374E903CDFA4C642" ) );
2387
2388 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002389 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002390
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002391 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2392 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002393 {
2394 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002395 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002396
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002397 ret = 1;
2398 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002399 }
2400
2401 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002402 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002403
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002404 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002406 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002407 "36E139AEA55215609D2816998ED020BB" \
2408 "BD96C37890F65171D948E9BC7CBAA4D9" \
2409 "325D24D6A3C12710F10A09FA08AB87" ) );
2410
2411 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002412 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002413
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002414 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 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_inv_mod( &X, &A, &N ) );
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 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2430 "C3DBA76456363A10869622EAC2DD84EC" \
2431 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2432
2433 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434 mbedtls_printf( " MPI test #4 (inv_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
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002448 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002449 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002450
Paul Bakker66d5d072014-06-17 16:39:18 +02002451 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002452 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002453 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2454 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002456 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002457
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002458 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002459 {
2460 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002461 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002462
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002463 ret = 1;
2464 goto cleanup;
2465 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002466 }
2467
2468 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002469 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002470
Paul Bakker5121ce52009-01-03 21:22:43 +00002471cleanup:
2472
2473 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002474 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002475
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002476 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2477 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002478
2479 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002480 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002481
2482 return( ret );
2483}
2484
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002485#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002486
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002487#endif /* MBEDTLS_BIGNUM_C */