blob: db46a0ecb5f0bc2df471972811550f0045a21a43 [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
Gilles Peskine6a269672020-01-20 21:17:43 +0100154 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100155 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine774c1632020-01-21 13:59:51 +0100157 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100158
159 for( i = X->n - 1; i > 0; i-- )
160 if( X->p[i] != 0 )
161 break;
162 i++;
163
164 if( i < nblimbs )
165 i = nblimbs;
166
Simon Butcher29176892016-05-20 00:19:09 +0100167 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200168 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100169
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100170 if( X->p != NULL )
171 {
172 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200173 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175 }
176
177 X->n = i;
178 X->p = p;
179
180 return( 0 );
181}
182
183/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000184 * Copy the contents of Y into X
185 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000187{
Paul Bakker23986e52011-04-24 08:57:21 +0000188 int ret;
189 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000190
191 if( X == Y )
192 return( 0 );
193
Gilles Peskine2aeab872020-01-20 21:12:50 +0100194 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200195 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200196 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200197 return( 0 );
198 }
199
Paul Bakker5121ce52009-01-03 21:22:43 +0000200 for( i = Y->n - 1; i > 0; i-- )
201 if( Y->p[i] != 0 )
202 break;
203 i++;
204
205 X->s = Y->s;
206
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000208
209 memset( X->p, 0, X->n * ciL );
210 memcpy( X->p, Y->p, i * ciL );
211
212cleanup:
213
214 return( ret );
215}
216
217/*
218 * Swap the contents of X and Y
219 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000221{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000223
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200224 memcpy( &T, X, sizeof( mbedtls_mpi ) );
225 memcpy( X, Y, sizeof( mbedtls_mpi ) );
226 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000227}
228
229/*
Gilles Peskine3c44c652020-06-04 19:14:58 +0200230 * Conditionally assign dest = src, without leaking information
231 * about whether the assignment was made or not.
232 * dest and src must be arrays of limbs of size n.
233 * assign must be 0 or 1.
234 */
235static void mpi_safe_cond_assign( size_t n,
236 mbedtls_mpi_uint *dest,
237 const mbedtls_mpi_uint *src,
238 unsigned char assign )
239{
240 size_t i;
241 for( i = 0; i < n; i++ )
242 dest[i] = dest[i] * ( 1 - assign ) + src[i] * assign;
243}
244
245/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100246 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100247 * about whether the assignment was made or not.
248 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100249 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100251{
252 int ret = 0;
253 size_t i;
254
Pascal Junodb99183d2015-03-11 16:49:45 +0100255 /* make sure assign is 0 or 1 in a time-constant manner */
256 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100257
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200258 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100259
Paul Bakker66d5d072014-06-17 16:39:18 +0200260 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100261
Gilles Peskine3c44c652020-06-04 19:14:58 +0200262 mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100263
Gilles Peskine3c44c652020-06-04 19:14:58 +0200264 for( i = Y->n; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200265 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100266
267cleanup:
268 return( ret );
269}
270
271/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100272 * Conditionally swap X and Y, without leaking information
273 * about whether the swap was made or not.
274 * Here it is not ok to simply swap the pointers, which whould lead to
275 * different memory access patterns when X and Y are used afterwards.
276 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200277int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100278{
279 int ret, s;
280 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100282
283 if( X == Y )
284 return( 0 );
285
Pascal Junodb99183d2015-03-11 16:49:45 +0100286 /* make sure swap is 0 or 1 in a time-constant manner */
287 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100288
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200289 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
290 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100291
292 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200293 X->s = X->s * ( 1 - swap ) + Y->s * swap;
294 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100295
296
297 for( i = 0; i < X->n; i++ )
298 {
299 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200300 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
301 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100302 }
303
304cleanup:
305 return( ret );
306}
307
308/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000309 * Set value from integer
310 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200311int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000312{
313 int ret;
314
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000316 memset( X->p, 0, X->n * ciL );
317
318 X->p[0] = ( z < 0 ) ? -z : z;
319 X->s = ( z < 0 ) ? -1 : 1;
320
321cleanup:
322
323 return( ret );
324}
325
326/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000327 * Get a specific bit
328 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200329int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000330{
331 if( X->n * biL <= pos )
332 return( 0 );
333
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200334 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000335}
336
Gilles Peskine220cc172018-11-20 16:47:47 +0100337/* Get a specific byte, without range checks. */
338#define GET_BYTE( X, i ) \
339 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
340
Paul Bakker2f5947e2011-05-18 15:47:11 +0000341/*
342 * Set a bit to a specific value of 0 or 1
343 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000345{
346 int ret = 0;
347 size_t off = pos / biL;
348 size_t idx = pos % biL;
349
350 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200352
Paul Bakker2f5947e2011-05-18 15:47:11 +0000353 if( X->n * biL <= pos )
354 {
355 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200356 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200358 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000359 }
360
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200361 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
362 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000363
364cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200365
Paul Bakker2f5947e2011-05-18 15:47:11 +0000366 return( ret );
367}
368
369/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200370 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000371 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200372size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000373{
Paul Bakker23986e52011-04-24 08:57:21 +0000374 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000375
376 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000377 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000378 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
379 return( count );
380
381 return( 0 );
382}
383
384/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000385 * Count leading zero bits in a given integer
386 */
387static size_t mbedtls_clz( const mbedtls_mpi_uint x )
388{
389 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100390 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000391
392 for( j = 0; j < biL; j++ )
393 {
394 if( x & mask ) break;
395
396 mask >>= 1;
397 }
398
399 return j;
400}
401
402/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200403 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000404 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200405size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000406{
Paul Bakker23986e52011-04-24 08:57:21 +0000407 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000408
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200409 if( X->n == 0 )
410 return( 0 );
411
Paul Bakker5121ce52009-01-03 21:22:43 +0000412 for( i = X->n - 1; i > 0; i-- )
413 if( X->p[i] != 0 )
414 break;
415
Simon Butcher15b15d12015-11-26 19:35:03 +0000416 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
Paul Bakker23986e52011-04-24 08:57:21 +0000418 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000419}
420
421/*
422 * Return the total size in bytes
423 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000425{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200426 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000427}
428
429/*
430 * Convert an ASCII character to digit value
431 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000433{
434 *d = 255;
435
436 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
437 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
438 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
439
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200440 if( *d >= (mbedtls_mpi_uint) radix )
441 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
443 return( 0 );
444}
445
446/*
447 * Import from an ASCII string
448 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000450{
Paul Bakker23986e52011-04-24 08:57:21 +0000451 int ret;
452 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453 mbedtls_mpi_uint d;
454 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000455
456 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000460
Paul Bakkerff60ee62010-03-16 21:09:09 +0000461 slen = strlen( s );
462
Paul Bakker5121ce52009-01-03 21:22:43 +0000463 if( radix == 16 )
464 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100465 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200466 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
467
Paul Bakkerff60ee62010-03-16 21:09:09 +0000468 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
471 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000472
Paul Bakker23986e52011-04-24 08:57:21 +0000473 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 {
Paul Bakker23986e52011-04-24 08:57:21 +0000475 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000476 {
477 X->s = -1;
478 break;
479 }
480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200482 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483 }
484 }
485 else
486 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000488
Paul Bakkerff60ee62010-03-16 21:09:09 +0000489 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000490 {
491 if( i == 0 && s[i] == '-' )
492 {
493 X->s = -1;
494 continue;
495 }
496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
498 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000499
500 if( X->s == 1 )
501 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000503 }
504 else
505 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200506 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000507 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000508 }
509 }
510
511cleanup:
512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000514
515 return( ret );
516}
517
518/*
Ron Eldore6cbfc32018-11-20 14:07:01 +0200519 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000520 */
Ron Eldore6cbfc32018-11-20 14:07:01 +0200521static int mpi_write_hlp( mbedtls_mpi *X, int radix,
522 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000523{
524 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525 mbedtls_mpi_uint r;
Ron Eldore6cbfc32018-11-20 14:07:01 +0200526 size_t length = 0;
527 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000528
Ron Eldore6cbfc32018-11-20 14:07:01 +0200529 do
530 {
531 if( length >= buflen )
532 {
533 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
534 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000535
Ron Eldore6cbfc32018-11-20 14:07:01 +0200536 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
537 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
538 /*
539 * Write the residue in the current position, as an ASCII character.
540 */
541 if( r < 0xA )
542 *(--p_end) = (char)( '0' + r );
543 else
544 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000545
Ron Eldore6cbfc32018-11-20 14:07:01 +0200546 length++;
547 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000548
Ron Eldore6cbfc32018-11-20 14:07:01 +0200549 memmove( *p, p_end, length );
550 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000551
552cleanup:
553
554 return( ret );
555}
556
557/*
558 * Export into an ASCII string
559 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100560int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
561 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000562{
Paul Bakker23986e52011-04-24 08:57:21 +0000563 int ret = 0;
564 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000565 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000567
568 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200569 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000570
Hanno Beckera277d4c2019-02-04 09:45:07 +0000571 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
572 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
573 * `n`. If radix > 4, this might be a strict
574 * overapproximation of the number of
575 * radix-adic digits needed to present `n`. */
576 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
577 * present `n`. */
578
Janos Follath216e7382019-03-06 13:43:02 +0000579 n += 1; /* Terminating null byte */
Hanno Beckera277d4c2019-02-04 09:45:07 +0000580 n += 1; /* Compensate for the divisions above, which round down `n`
581 * in case it's not even. */
582 n += 1; /* Potential '-'-sign. */
583 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
584 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000585
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100586 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000587 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100588 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200589 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000590 }
591
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100592 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200593 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000594
595 if( X->s == -1 )
Hanno Beckereff335d2019-02-01 16:41:30 +0000596 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000597 *p++ = '-';
Hanno Beckereff335d2019-02-01 16:41:30 +0000598 buflen--;
599 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000600
601 if( radix == 16 )
602 {
Paul Bakker23986e52011-04-24 08:57:21 +0000603 int c;
604 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000605
Paul Bakker23986e52011-04-24 08:57:21 +0000606 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000607 {
Paul Bakker23986e52011-04-24 08:57:21 +0000608 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000609 {
Paul Bakker23986e52011-04-24 08:57:21 +0000610 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000611
Paul Bakker6c343d72014-07-10 14:36:19 +0200612 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000613 continue;
614
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000615 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000616 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000617 k = 1;
618 }
619 }
620 }
621 else
622 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200623 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000624
625 if( T.s == -1 )
626 T.s = 1;
627
Ron Eldore6cbfc32018-11-20 14:07:01 +0200628 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000629 }
630
631 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100632 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000633
634cleanup:
635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200636 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000637
638 return( ret );
639}
640
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000642/*
643 * Read X from an opened file
644 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200645int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000646{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200647 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000648 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000649 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000650 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000651 * Buffer should have space for (short) label and decimal formatted MPI,
652 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000653 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200654 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000655
656 memset( s, 0, sizeof( s ) );
657 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000659
660 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000661 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000663
Hanno Beckerb2034b72017-04-26 11:46:46 +0100664 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
665 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000666
667 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100668 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000669 if( mpi_get_digit( &d, radix, *p ) != 0 )
670 break;
671
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000673}
674
675/*
676 * Write X into an opened file (or stdout if fout == NULL)
677 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000679{
Paul Bakker23986e52011-04-24 08:57:21 +0000680 int ret;
681 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000682 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000683 * Buffer should have space for (short) label and decimal formatted MPI,
684 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000685 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200686 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000687
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100688 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000689
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100690 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
692 if( p == NULL ) p = "";
693
694 plen = strlen( p );
695 slen = strlen( s );
696 s[slen++] = '\r';
697 s[slen++] = '\n';
698
699 if( fout != NULL )
700 {
701 if( fwrite( p, 1, plen, fout ) != plen ||
702 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000704 }
705 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
708cleanup:
709
710 return( ret );
711}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200712#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000713
714/*
715 * Import X from unsigned binary data, big endian
716 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200717int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000718{
Paul Bakker23986e52011-04-24 08:57:21 +0000719 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100720 size_t i, j;
721 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000722
Hanno Becker073c1992017-10-17 15:17:27 +0100723 /* Ensure that target MPI has exactly the necessary number of limbs */
724 if( X->n != limbs )
725 {
726 mbedtls_mpi_free( X );
727 mbedtls_mpi_init( X );
728 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
729 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000730
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000732
Hanno Becker073c1992017-10-17 15:17:27 +0100733 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200734 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000735
736cleanup:
737
738 return( ret );
739}
740
741/*
742 * Export X into unsigned binary data, big endian
743 */
Gilles Peskine220cc172018-11-20 16:47:47 +0100744int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
745 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000746{
Gilles Peskine220cc172018-11-20 16:47:47 +0100747 size_t stored_bytes = X->n * ciL;
748 size_t bytes_to_copy;
749 unsigned char *p;
750 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000751
Gilles Peskine220cc172018-11-20 16:47:47 +0100752 if( stored_bytes < buflen )
753 {
754 /* There is enough space in the output buffer. Write initial
755 * null bytes and record the position at which to start
756 * writing the significant bytes. In this case, the execution
757 * trace of this function does not depend on the value of the
758 * number. */
759 bytes_to_copy = stored_bytes;
760 p = buf + buflen - stored_bytes;
761 memset( buf, 0, buflen - stored_bytes );
762 }
763 else
764 {
765 /* The output buffer is smaller than the allocated size of X.
766 * However X may fit if its leading bytes are zero. */
767 bytes_to_copy = buflen;
768 p = buf;
769 for( i = bytes_to_copy; i < stored_bytes; i++ )
770 {
771 if( GET_BYTE( X, i ) != 0 )
772 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
773 }
774 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000775
Gilles Peskine220cc172018-11-20 16:47:47 +0100776 for( i = 0; i < bytes_to_copy; i++ )
777 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000778
779 return( 0 );
780}
781
782/*
783 * Left-shift: X <<= count
784 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200785int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000786{
Paul Bakker23986e52011-04-24 08:57:21 +0000787 int ret;
788 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200789 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000790
791 v0 = count / (biL );
792 t1 = count & (biL - 1);
793
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200794 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000795
Paul Bakkerf9688572011-05-05 10:00:45 +0000796 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200797 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000798
799 ret = 0;
800
801 /*
802 * shift by count / limb_size
803 */
804 if( v0 > 0 )
805 {
Paul Bakker23986e52011-04-24 08:57:21 +0000806 for( i = X->n; i > v0; i-- )
807 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000808
Paul Bakker23986e52011-04-24 08:57:21 +0000809 for( ; i > 0; i-- )
810 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000811 }
812
813 /*
814 * shift by count % limb_size
815 */
816 if( t1 > 0 )
817 {
818 for( i = v0; i < X->n; i++ )
819 {
820 r1 = X->p[i] >> (biL - t1);
821 X->p[i] <<= t1;
822 X->p[i] |= r0;
823 r0 = r1;
824 }
825 }
826
827cleanup:
828
829 return( ret );
830}
831
832/*
833 * Right-shift: X >>= count
834 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200835int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000836{
Paul Bakker23986e52011-04-24 08:57:21 +0000837 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200838 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000839
840 v0 = count / biL;
841 v1 = count & (biL - 1);
842
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100843 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200844 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100845
Paul Bakker5121ce52009-01-03 21:22:43 +0000846 /*
847 * shift by count / limb_size
848 */
849 if( v0 > 0 )
850 {
851 for( i = 0; i < X->n - v0; i++ )
852 X->p[i] = X->p[i + v0];
853
854 for( ; i < X->n; i++ )
855 X->p[i] = 0;
856 }
857
858 /*
859 * shift by count % limb_size
860 */
861 if( v1 > 0 )
862 {
Paul Bakker23986e52011-04-24 08:57:21 +0000863 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000864 {
Paul Bakker23986e52011-04-24 08:57:21 +0000865 r1 = X->p[i - 1] << (biL - v1);
866 X->p[i - 1] >>= v1;
867 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000868 r0 = r1;
869 }
870 }
871
872 return( 0 );
873}
874
875/*
876 * Compare unsigned values
877 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200878int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000879{
Paul Bakker23986e52011-04-24 08:57:21 +0000880 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000881
Paul Bakker23986e52011-04-24 08:57:21 +0000882 for( i = X->n; i > 0; i-- )
883 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000884 break;
885
Paul Bakker23986e52011-04-24 08:57:21 +0000886 for( j = Y->n; j > 0; j-- )
887 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000888 break;
889
Paul Bakker23986e52011-04-24 08:57:21 +0000890 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000891 return( 0 );
892
893 if( i > j ) return( 1 );
894 if( j > i ) return( -1 );
895
Paul Bakker23986e52011-04-24 08:57:21 +0000896 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000897 {
Paul Bakker23986e52011-04-24 08:57:21 +0000898 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
899 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000900 }
901
902 return( 0 );
903}
904
905/*
906 * Compare signed values
907 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200908int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000909{
Paul Bakker23986e52011-04-24 08:57:21 +0000910 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000911
Paul Bakker23986e52011-04-24 08:57:21 +0000912 for( i = X->n; i > 0; i-- )
913 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000914 break;
915
Paul Bakker23986e52011-04-24 08:57:21 +0000916 for( j = Y->n; j > 0; j-- )
917 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000918 break;
919
Paul Bakker23986e52011-04-24 08:57:21 +0000920 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000921 return( 0 );
922
923 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000924 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000925
926 if( X->s > 0 && Y->s < 0 ) return( 1 );
927 if( Y->s > 0 && X->s < 0 ) return( -1 );
928
Paul Bakker23986e52011-04-24 08:57:21 +0000929 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000930 {
Paul Bakker23986e52011-04-24 08:57:21 +0000931 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
932 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000933 }
934
935 return( 0 );
936}
937
Janos Follath3173a532019-10-14 09:09:32 +0100938/** Decide if an integer is less than the other, without branches.
939 *
940 * \param x First integer.
941 * \param y Second integer.
942 *
943 * \return 1 if \p x is less than \p y, 0 otherwise
944 */
Janos Follathc3b376e2019-10-11 14:21:53 +0100945static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
946 const mbedtls_mpi_uint y )
Janos Follathe0187b92019-09-05 14:47:19 +0100947{
948 mbedtls_mpi_uint ret;
949 mbedtls_mpi_uint cond;
950
951 /*
952 * Check if the most significant bits (MSB) of the operands are different.
953 */
954 cond = ( x ^ y );
955 /*
956 * If the MSB are the same then the difference x-y will be negative (and
957 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
958 */
959 ret = ( x - y ) & ~cond;
960 /*
961 * If the MSB are different, then the operand with the MSB of 1 is the
962 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
963 * the MSB of y is 0.)
964 */
965 ret |= y & cond;
966
967
Janos Follathdb9f4492019-10-14 08:59:14 +0100968 ret = ret >> ( biL - 1 );
Janos Follathe0187b92019-09-05 14:47:19 +0100969
Janos Follath58239612019-10-29 15:08:46 +0000970 return (unsigned) ret;
Janos Follathe0187b92019-09-05 14:47:19 +0100971}
972
973/*
974 * Compare signed values in constant time
975 */
Janos Follathc3b376e2019-10-11 14:21:53 +0100976int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
977 unsigned *ret )
Janos Follathe0187b92019-09-05 14:47:19 +0100978{
979 size_t i;
Janos Follatha2b9a962019-10-28 12:23:18 +0000980 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath8ec2a952019-10-28 12:31:34 +0000981 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathe0187b92019-09-05 14:47:19 +0100982
983 if( X->n != Y->n )
984 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
985
986 /*
Janos Follath51ed14e2019-10-28 12:12:15 +0000987 * Set sign_N to 1 if N >= 0, 0 if N < 0.
988 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathe0187b92019-09-05 14:47:19 +0100989 */
Janos Follath8ec2a952019-10-28 12:31:34 +0000990 X_is_negative = ( X->s & 2 ) >> 1;
991 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follathc3b376e2019-10-11 14:21:53 +0100992
993 /*
994 * If the signs are different, then the positive operand is the bigger.
Janos Follath8ec2a952019-10-28 12:31:34 +0000995 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
996 * is false if X is positive (X_is_negative == 0).
Janos Follathc3b376e2019-10-11 14:21:53 +0100997 */
Janos Follath8ec2a952019-10-28 12:31:34 +0000998 cond = ( X_is_negative ^ Y_is_negative );
999 *ret = cond & X_is_negative;
Janos Follathc3b376e2019-10-11 14:21:53 +01001000
1001 /*
Janos Follatha2b9a962019-10-28 12:23:18 +00001002 * This is a constant-time function. We might have the result, but we still
Janos Follathc3b376e2019-10-11 14:21:53 +01001003 * need to go through the loop. Record if we have the result already.
1004 */
Janos Follathe0187b92019-09-05 14:47:19 +01001005 done = cond;
1006
1007 for( i = X->n; i > 0; i-- )
1008 {
1009 /*
Janos Follathb4edac52019-11-05 12:24:52 +00001010 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1011 * X and Y are negative.
Janos Follathc3b376e2019-10-11 14:21:53 +01001012 *
1013 * Again even if we can make a decision, we just mark the result and
1014 * the fact that we are done and continue looping.
Janos Follathe0187b92019-09-05 14:47:19 +01001015 */
Janos Follathb4edac52019-11-05 12:24:52 +00001016 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1017 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathcff9e6e2019-10-28 12:37:21 +00001018 done |= cond;
Janos Follathe0187b92019-09-05 14:47:19 +01001019
1020 /*
Janos Follathb4edac52019-11-05 12:24:52 +00001021 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1022 * X and Y are positive.
Janos Follathc3b376e2019-10-11 14:21:53 +01001023 *
1024 * Again even if we can make a decision, we just mark the result and
1025 * the fact that we are done and continue looping.
Janos Follathe0187b92019-09-05 14:47:19 +01001026 */
Janos Follathb4edac52019-11-05 12:24:52 +00001027 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1028 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathcff9e6e2019-10-28 12:37:21 +00001029 done |= cond;
Janos Follathe0187b92019-09-05 14:47:19 +01001030 }
1031
1032 return( 0 );
1033}
1034
Paul Bakker5121ce52009-01-03 21:22:43 +00001035/*
1036 * Compare signed values
1037 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001038int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001039{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001040 mbedtls_mpi Y;
1041 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001042
1043 *p = ( z < 0 ) ? -z : z;
1044 Y.s = ( z < 0 ) ? -1 : 1;
1045 Y.n = 1;
1046 Y.p = p;
1047
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001048 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001049}
1050
1051/*
1052 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1053 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001054int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001055{
Paul Bakker23986e52011-04-24 08:57:21 +00001056 int ret;
1057 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001058 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +00001059
1060 if( X == B )
1061 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001062 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001063 }
1064
1065 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001066 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001067
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001068 /*
1069 * X should always be positive as a result of unsigned additions.
1070 */
1071 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001072
Paul Bakker23986e52011-04-24 08:57:21 +00001073 for( j = B->n; j > 0; j-- )
1074 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001075 break;
1076
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001077 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001078
1079 o = B->p; p = X->p; c = 0;
1080
Janos Follath6c922682015-10-30 17:43:11 +01001081 /*
1082 * tmp is used because it might happen that p == o
1083 */
Paul Bakker23986e52011-04-24 08:57:21 +00001084 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001085 {
Janos Follath6c922682015-10-30 17:43:11 +01001086 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001087 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001088 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001089 }
1090
1091 while( c != 0 )
1092 {
1093 if( i >= X->n )
1094 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001095 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001096 p = X->p + i;
1097 }
1098
Paul Bakker2d319fd2012-09-16 21:34:26 +00001099 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001100 }
1101
1102cleanup:
1103
1104 return( ret );
1105}
1106
1107/*
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001108 * Helper for mbedtls_mpi subtraction.
1109 *
1110 * Calculate d - s where d and s have the same size.
1111 * This function operates modulo (2^ciL)^n and returns the carry
1112 * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise).
1113 *
1114 * \param n Number of limbs of \p d and \p s.
1115 * \param[in,out] d On input, the left operand.
1116 * On output, the result of the subtraction:
1117 * \param[s] The right operand.
1118 *
1119 * \return 1 if `d < s`.
1120 * 0 if `d >= s`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001121 */
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001122static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1123 mbedtls_mpi_uint *d,
1124 const mbedtls_mpi_uint *s )
Paul Bakker5121ce52009-01-03 21:22:43 +00001125{
Paul Bakker23986e52011-04-24 08:57:21 +00001126 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001127 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001128
1129 for( i = c = 0; i < n; i++, s++, d++ )
1130 {
1131 z = ( *d < c ); *d -= c;
1132 c = ( *d < *s ) + z; *d -= *s;
1133 }
1134
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001135 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001136}
1137
1138/*
Gilles Peskinefa85cc22020-06-08 22:50:35 +02001139 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001140 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001141int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001142{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001143 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001144 int ret;
1145 size_t n;
Gilles Peskinefa85cc22020-06-08 22:50:35 +02001146 mbedtls_mpi_uint carry;
Paul Bakker5121ce52009-01-03 21:22:43 +00001147
Gilles Peskinefa85cc22020-06-08 22:50:35 +02001148 /* if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) */
1149 /* return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); */
Paul Bakker5121ce52009-01-03 21:22:43 +00001150
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001151 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001152
1153 if( X == B )
1154 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001155 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001156 B = &TB;
1157 }
1158
1159 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001160 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001161
Paul Bakker1ef7a532009-06-20 10:50:55 +00001162 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001163 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001164 */
1165 X->s = 1;
1166
Paul Bakker5121ce52009-01-03 21:22:43 +00001167 ret = 0;
1168
Paul Bakker23986e52011-04-24 08:57:21 +00001169 for( n = B->n; n > 0; n-- )
1170 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001171 break;
1172
Gilles Peskinefa85cc22020-06-08 22:50:35 +02001173 carry = mpi_sub_hlp( n, X->p, B->p );
1174 if( carry != 0 )
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001175 {
Gilles Peskinefa85cc22020-06-08 22:50:35 +02001176 /* Propagate the carry to the first nonzero limb of X. */
1177 for( ; n < X->n && X->p[n] == 0; n++ )
1178 --X->p[n];
1179 /* If we ran out of space for the carry, it means that the result
1180 * is negative. */
1181 if( n == X->n )
1182 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
1183 --X->p[n];
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001184 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001185
1186cleanup:
1187
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001188 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001189
1190 return( ret );
1191}
1192
1193/*
1194 * Signed addition: X = A + B
1195 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001196int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001197{
1198 int ret, s = A->s;
1199
1200 if( A->s * B->s < 0 )
1201 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001202 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001203 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001204 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001205 X->s = s;
1206 }
1207 else
1208 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001209 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001210 X->s = -s;
1211 }
1212 }
1213 else
1214 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001215 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001216 X->s = s;
1217 }
1218
1219cleanup:
1220
1221 return( ret );
1222}
1223
1224/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001225 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001226 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001227int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001228{
1229 int ret, s = A->s;
1230
1231 if( A->s * B->s > 0 )
1232 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001233 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001234 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001235 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001236 X->s = s;
1237 }
1238 else
1239 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001240 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001241 X->s = -s;
1242 }
1243 }
1244 else
1245 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001246 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001247 X->s = s;
1248 }
1249
1250cleanup:
1251
1252 return( ret );
1253}
1254
1255/*
1256 * Signed addition: X = A + b
1257 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001258int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001259{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001260 mbedtls_mpi _B;
1261 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001262
1263 p[0] = ( b < 0 ) ? -b : b;
1264 _B.s = ( b < 0 ) ? -1 : 1;
1265 _B.n = 1;
1266 _B.p = p;
1267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001268 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001269}
1270
1271/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001272 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001273 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001274int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001275{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001276 mbedtls_mpi _B;
1277 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001278
1279 p[0] = ( b < 0 ) ? -b : b;
1280 _B.s = ( b < 0 ) ? -1 : 1;
1281 _B.n = 1;
1282 _B.p = p;
1283
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001284 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001285}
1286
1287/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001288 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001289 */
1290static
1291#if defined(__APPLE__) && defined(__arm__)
1292/*
1293 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1294 * appears to need this to prevent bad ARM code generation at -O3.
1295 */
1296__attribute__ ((noinline))
1297#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001298void 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 +00001299{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001300 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001301
1302#if defined(MULADDC_HUIT)
1303 for( ; i >= 8; i -= 8 )
1304 {
1305 MULADDC_INIT
1306 MULADDC_HUIT
1307 MULADDC_STOP
1308 }
1309
1310 for( ; i > 0; i-- )
1311 {
1312 MULADDC_INIT
1313 MULADDC_CORE
1314 MULADDC_STOP
1315 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001316#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001317 for( ; i >= 16; i -= 16 )
1318 {
1319 MULADDC_INIT
1320 MULADDC_CORE MULADDC_CORE
1321 MULADDC_CORE MULADDC_CORE
1322 MULADDC_CORE MULADDC_CORE
1323 MULADDC_CORE MULADDC_CORE
1324
1325 MULADDC_CORE MULADDC_CORE
1326 MULADDC_CORE MULADDC_CORE
1327 MULADDC_CORE MULADDC_CORE
1328 MULADDC_CORE MULADDC_CORE
1329 MULADDC_STOP
1330 }
1331
1332 for( ; i >= 8; i -= 8 )
1333 {
1334 MULADDC_INIT
1335 MULADDC_CORE MULADDC_CORE
1336 MULADDC_CORE MULADDC_CORE
1337
1338 MULADDC_CORE MULADDC_CORE
1339 MULADDC_CORE MULADDC_CORE
1340 MULADDC_STOP
1341 }
1342
1343 for( ; i > 0; i-- )
1344 {
1345 MULADDC_INIT
1346 MULADDC_CORE
1347 MULADDC_STOP
1348 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001349#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001350
1351 t++;
1352
1353 do {
1354 *d += c; c = ( *d < c ); d++;
1355 }
1356 while( c != 0 );
1357}
1358
1359/*
1360 * Baseline multiplication: X = A * B (HAC 14.12)
1361 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001362int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001363{
Paul Bakker23986e52011-04-24 08:57:21 +00001364 int ret;
1365 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001367
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001368 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001370 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1371 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001372
Paul Bakker23986e52011-04-24 08:57:21 +00001373 for( i = A->n; i > 0; i-- )
1374 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001375 break;
1376
Paul Bakker23986e52011-04-24 08:57:21 +00001377 for( j = B->n; j > 0; j-- )
1378 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001379 break;
1380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001381 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1382 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001383
Paul Bakker23986e52011-04-24 08:57:21 +00001384 for( i++; j > 0; j-- )
1385 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001386
1387 X->s = A->s * B->s;
1388
1389cleanup:
1390
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001392
1393 return( ret );
1394}
1395
1396/*
1397 * Baseline multiplication: X = A * b
1398 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001400{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001401 mbedtls_mpi _B;
1402 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001403
1404 _B.s = 1;
1405 _B.n = 1;
1406 _B.p = p;
1407 p[0] = b;
1408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001409 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001410}
1411
1412/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001413 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1414 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001415 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001416static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1417 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001418{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001419#if defined(MBEDTLS_HAVE_UDBL)
1420 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001421#else
Simon Butcher9803d072016-01-03 00:24:34 +00001422 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1423 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001424 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1425 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001426 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001427#endif
1428
Simon Butcher15b15d12015-11-26 19:35:03 +00001429 /*
1430 * Check for overflow
1431 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001432 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001433 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001434 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001435
Simon Butcherf5ba0452015-12-27 23:01:55 +00001436 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001437 }
1438
1439#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001440 dividend = (mbedtls_t_udbl) u1 << biL;
1441 dividend |= (mbedtls_t_udbl) u0;
1442 quotient = dividend / d;
1443 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1444 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1445
1446 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001447 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001448
1449 return (mbedtls_mpi_uint) quotient;
1450#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001451
1452 /*
1453 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1454 * Vol. 2 - Seminumerical Algorithms, Knuth
1455 */
1456
1457 /*
1458 * Normalize the divisor, d, and dividend, u0, u1
1459 */
1460 s = mbedtls_clz( d );
1461 d = d << s;
1462
1463 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001464 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001465 u0 = u0 << s;
1466
1467 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001468 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001469
1470 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001471 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001472
1473 /*
1474 * Find the first quotient and remainder
1475 */
1476 q1 = u1 / d1;
1477 r0 = u1 - d1 * q1;
1478
1479 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1480 {
1481 q1 -= 1;
1482 r0 += d1;
1483
1484 if ( r0 >= radix ) break;
1485 }
1486
Simon Butcherf5ba0452015-12-27 23:01:55 +00001487 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001488 q0 = rAX / d1;
1489 r0 = rAX - q0 * d1;
1490
1491 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1492 {
1493 q0 -= 1;
1494 r0 += d1;
1495
1496 if ( r0 >= radix ) break;
1497 }
1498
1499 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001500 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001501
1502 quotient = q1 * radix + q0;
1503
1504 return quotient;
1505#endif
1506}
1507
1508/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001509 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001510 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511int 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 +00001512{
Paul Bakker23986e52011-04-24 08:57:21 +00001513 int ret;
1514 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001515 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001516
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001517 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1518 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001519
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001520 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1521 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001522
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001523 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001524 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001525 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1526 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001527 return( 0 );
1528 }
1529
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001530 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1531 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001532 X.s = Y.s = 1;
1533
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001534 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1535 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1536 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1537 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001538
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001539 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001540 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001541 {
1542 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001543 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1544 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001545 }
1546 else k = 0;
1547
1548 n = X.n - 1;
1549 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001550 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001552 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001553 {
1554 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001555 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001556 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001557 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001558
1559 for( i = n; i > t ; i-- )
1560 {
1561 if( X.p[i] >= Y.p[t] )
1562 Z.p[i - t - 1] = ~0;
1563 else
1564 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001565 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1566 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001567 }
1568
1569 Z.p[i - t - 1]++;
1570 do
1571 {
1572 Z.p[i - t - 1]--;
1573
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001574 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001575 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001576 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001577 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001578
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001579 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001580 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1581 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001582 T2.p[2] = X.p[i];
1583 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001584 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001585
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001586 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1587 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1588 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001589
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001590 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001591 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001592 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1593 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1594 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001595 Z.p[i - t - 1]--;
1596 }
1597 }
1598
1599 if( Q != NULL )
1600 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001601 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001602 Q->s = A->s * B->s;
1603 }
1604
1605 if( R != NULL )
1606 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001607 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001608 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001609 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001610
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001611 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001612 R->s = 1;
1613 }
1614
1615cleanup:
1616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001617 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1618 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001619
1620 return( ret );
1621}
1622
1623/*
1624 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001625 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001626int 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 +00001627{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001628 mbedtls_mpi _B;
1629 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001630
1631 p[0] = ( b < 0 ) ? -b : b;
1632 _B.s = ( b < 0 ) ? -1 : 1;
1633 _B.n = 1;
1634 _B.p = p;
1635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001637}
1638
1639/*
1640 * Modulo: R = A mod B
1641 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001642int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001643{
1644 int ret;
1645
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001646 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1647 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001648
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001649 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001650
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1652 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001653
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001654 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1655 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001656
1657cleanup:
1658
1659 return( ret );
1660}
1661
1662/*
1663 * Modulo: r = A mod b
1664 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001665int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001666{
Paul Bakker23986e52011-04-24 08:57:21 +00001667 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001668 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001669
1670 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001672
1673 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001674 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001675
1676 /*
1677 * handle trivial cases
1678 */
1679 if( b == 1 )
1680 {
1681 *r = 0;
1682 return( 0 );
1683 }
1684
1685 if( b == 2 )
1686 {
1687 *r = A->p[0] & 1;
1688 return( 0 );
1689 }
1690
1691 /*
1692 * general case
1693 */
Paul Bakker23986e52011-04-24 08:57:21 +00001694 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001695 {
Paul Bakker23986e52011-04-24 08:57:21 +00001696 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001697 y = ( y << biH ) | ( x >> biH );
1698 z = y / b;
1699 y -= z * b;
1700
1701 x <<= biH;
1702 y = ( y << biH ) | ( x >> biH );
1703 z = y / b;
1704 y -= z * b;
1705 }
1706
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001707 /*
1708 * If A is negative, then the current y represents a negative value.
1709 * Flipping it to the positive side.
1710 */
1711 if( A->s < 0 && y != 0 )
1712 y = b - y;
1713
Paul Bakker5121ce52009-01-03 21:22:43 +00001714 *r = y;
1715
1716 return( 0 );
1717}
1718
1719/*
1720 * Fast Montgomery initialization (thanks to Tom St Denis)
1721 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001722static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001723{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001724 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001725 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001726
1727 x = m0;
1728 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001729
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001730 for( i = biL; i >= 8; i /= 2 )
1731 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001732
1733 *mm = ~x + 1;
1734}
1735
Gilles Peskined108d072020-06-04 15:00:49 +02001736/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1737 *
1738 * \param[in,out] A One of the numbers to multiply.
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001739 * It must have at least as many limbs as N
1740 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskined108d072020-06-04 15:00:49 +02001741 * On successful completion, A contains the result of
1742 * the multiplication A * B * R^-1 mod N where
1743 * R = (2^ciL)^n.
1744 * \param[in] B One of the numbers to multiply.
1745 * It must be nonzero and must not have more limbs than N
1746 * (B->n <= N->n).
1747 * \param[in] N The modulo. N must be odd.
1748 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1749 * This is -N^-1 mod 2^ciL.
1750 * \param[in,out] T A bignum for temporary storage.
1751 * It must be at least twice the limb size of N plus 2
1752 * (T->n >= 2 * (N->n + 1)).
1753 * Its initial content is unused and
1754 * its final content is indeterminate.
1755 * Note that unlike the usual convention in the library
1756 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00001757 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001758static void 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 +02001759 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001760{
Paul Bakker23986e52011-04-24 08:57:21 +00001761 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001762 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001763
1764 memset( T->p, 0, T->n * ciL );
1765
1766 d = T->p;
1767 n = N->n;
1768 m = ( B->n < n ) ? B->n : n;
1769
1770 for( i = 0; i < n; i++ )
1771 {
1772 /*
1773 * T = (T + u0*B + u1*N) / 2^biL
1774 */
1775 u0 = A->p[i];
1776 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1777
1778 mpi_mul_hlp( m, B->p, d, u0 );
1779 mpi_mul_hlp( n, N->p, d, u1 );
1780
1781 *d++ = u0; d[n + 1] = 0;
1782 }
1783
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001784 /* At this point, d is either the desired result or the desired result
1785 * plus N. We now potentially subtract N, avoiding leaking whether the
1786 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001787
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001788 /* Copy the n least significant limbs of d to A, so that
1789 * A = d if d < N (recall that N has n limbs). */
1790 memcpy( A->p, d, n * ciL );
1791 /* If d >= N then we want to set A to N - d. To prevent timing attacks,
1792 * do the calculation without using conditional tests. */
1793 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine7ff812e2020-06-04 21:05:24 +02001794 d[n] += 1;
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001795 d[n] -= mpi_sub_hlp( n, d, N->p );
Gilles Peskinecc6a6bf2020-06-08 22:37:50 +02001796 /* If d0 < N then d < (2^biL)^n
1797 * so d[n] == 0 and we want to keep A as it is.
1798 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
1799 * so d[n] == 1 and we want to set A to the result of the subtraction
1800 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
1801 * This exactly corresponds to a conditional assignment. */
1802 mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001803}
1804
1805/*
1806 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskined108d072020-06-04 15:00:49 +02001807 *
1808 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001809 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001810static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001811{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001812 mbedtls_mpi_uint z = 1;
1813 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001814
Paul Bakker8ddb6452013-02-27 14:56:33 +01001815 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001816 U.p = &z;
1817
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001818 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001819}
1820
1821/*
1822 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1823 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824int 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 +00001825{
Paul Bakker23986e52011-04-24 08:57:21 +00001826 int ret;
1827 size_t wbits, wsize, one = 1;
1828 size_t i, j, nblimbs;
1829 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830 mbedtls_mpi_uint ei, mm, state;
1831 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001832 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001833
Hanno Becker930ec7d2018-03-09 10:48:00 +00001834 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001835 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001836
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001837 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1838 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001839
1840 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001841 * Init temps and window size
1842 */
1843 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1845 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846 memset( W, 0, sizeof( W ) );
1847
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001848 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001849
1850 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1851 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1852
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001853#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001854 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1855 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001856#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001857
Paul Bakker5121ce52009-01-03 21:22:43 +00001858 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001859 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1860 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1861 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001862
1863 /*
Paul Bakker50546922012-05-19 08:40:49 +00001864 * Compensate for negative A (and correct at the end)
1865 */
1866 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001867 if( neg )
1868 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001869 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001870 Apos.s = 1;
1871 A = &Apos;
1872 }
1873
1874 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001875 * If 1st call, pre-compute R^2 mod N
1876 */
1877 if( _RR == NULL || _RR->p == NULL )
1878 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1880 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1881 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001882
1883 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001884 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001885 }
1886 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001887 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001888
1889 /*
1890 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1891 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001892 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1893 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001894 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001895 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001896
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001897 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001898
1899 /*
1900 * X = R^2 * R^-1 mod N = R mod N
1901 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001902 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001903 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001904
1905 if( wsize > 1 )
1906 {
1907 /*
1908 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1909 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001910 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001911
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001912 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1913 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001914
1915 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001916 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001917
Paul Bakker5121ce52009-01-03 21:22:43 +00001918 /*
1919 * W[i] = W[i - 1] * W[1]
1920 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001921 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001922 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001923 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1924 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001925
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001926 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001927 }
1928 }
1929
1930 nblimbs = E->n;
1931 bufsize = 0;
1932 nbits = 0;
1933 wbits = 0;
1934 state = 0;
1935
1936 while( 1 )
1937 {
1938 if( bufsize == 0 )
1939 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001940 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001941 break;
1942
Paul Bakker0d7702c2013-10-29 16:18:35 +01001943 nblimbs--;
1944
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001945 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001946 }
1947
1948 bufsize--;
1949
1950 ei = (E->p[nblimbs] >> bufsize) & 1;
1951
1952 /*
1953 * skip leading 0s
1954 */
1955 if( ei == 0 && state == 0 )
1956 continue;
1957
1958 if( ei == 0 && state == 1 )
1959 {
1960 /*
1961 * out of window, square X
1962 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001963 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001964 continue;
1965 }
1966
1967 /*
1968 * add ei to current window
1969 */
1970 state = 2;
1971
1972 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001973 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001974
1975 if( nbits == wsize )
1976 {
1977 /*
1978 * X = X^wsize R^-1 mod N
1979 */
1980 for( i = 0; i < wsize; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001981 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001982
1983 /*
1984 * X = X * W[wbits] R^-1 mod N
1985 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001986 mpi_montmul( X, &W[wbits], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001987
1988 state--;
1989 nbits = 0;
1990 wbits = 0;
1991 }
1992 }
1993
1994 /*
1995 * process the remaining bits
1996 */
1997 for( i = 0; i < nbits; i++ )
1998 {
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001999 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002000
2001 wbits <<= 1;
2002
Paul Bakker66d5d072014-06-17 16:39:18 +02002003 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002004 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002005 }
2006
2007 /*
2008 * X = A^E * R * R^-1 mod N = A^E mod N
2009 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02002010 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002011
Hanno Beckera4af1c42017-04-18 09:07:45 +01002012 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002013 {
2014 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002015 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002016 }
2017
Paul Bakker5121ce52009-01-03 21:22:43 +00002018cleanup:
2019
Paul Bakker66d5d072014-06-17 16:39:18 +02002020 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002021 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002024
Paul Bakker75a28602014-03-31 12:08:17 +02002025 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002026 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002027
2028 return( ret );
2029}
2030
Paul Bakker5121ce52009-01-03 21:22:43 +00002031/*
2032 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2033 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002035{
Paul Bakker23986e52011-04-24 08:57:21 +00002036 int ret;
2037 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002038 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002039
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002040 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002041
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002042 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2043 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002044
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002045 lz = mbedtls_mpi_lsb( &TA );
2046 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002047
Paul Bakker66d5d072014-06-17 16:39:18 +02002048 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002049 lz = lzt;
2050
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002051 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2052 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002053
Paul Bakker5121ce52009-01-03 21:22:43 +00002054 TA.s = TB.s = 1;
2055
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002056 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002057 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2059 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002060
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002061 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002062 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002063 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2064 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002065 }
2066 else
2067 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002068 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2069 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002070 }
2071 }
2072
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002073 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2074 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002075
2076cleanup:
2077
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002078 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002079
2080 return( ret );
2081}
2082
Paul Bakker33dc46b2014-04-30 16:11:39 +02002083/*
2084 * Fill X with size bytes of random.
2085 *
2086 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002087 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002088 * deterministic, eg for tests).
2089 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002090int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002091 int (*f_rng)(void *, unsigned char *, size_t),
2092 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002093{
Paul Bakker23986e52011-04-24 08:57:21 +00002094 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002095 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02002096
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002097 if( size > MBEDTLS_MPI_MAX_SIZE )
2098 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002099
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002100 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2101 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002102
2103cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01002104 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002105 return( ret );
2106}
2107
Paul Bakker5121ce52009-01-03 21:22:43 +00002108/*
2109 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2110 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002111int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002112{
2113 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002114 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002115
Hanno Becker4bcb4912017-04-18 15:49:39 +01002116 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002117 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002119 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2120 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2121 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002123 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002125 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002126 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002127 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002128 goto cleanup;
2129 }
2130
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002131 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2132 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2133 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2134 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002135
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002136 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2137 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2138 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2139 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002140
2141 do
2142 {
2143 while( ( TU.p[0] & 1 ) == 0 )
2144 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002146
2147 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2148 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002149 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2150 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002151 }
2152
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002153 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2154 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002155 }
2156
2157 while( ( TV.p[0] & 1 ) == 0 )
2158 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002159 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002160
2161 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2162 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002163 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2164 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002165 }
2166
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002167 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2168 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002169 }
2170
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002171 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002172 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002173 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2174 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2175 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002176 }
2177 else
2178 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002179 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2180 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2181 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002182 }
2183 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002185
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002186 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2187 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002189 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2190 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002192 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002193
2194cleanup:
2195
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002196 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2197 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2198 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002199
2200 return( ret );
2201}
2202
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002203#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002204
Paul Bakker5121ce52009-01-03 21:22:43 +00002205static const int small_prime[] =
2206{
2207 3, 5, 7, 11, 13, 17, 19, 23,
2208 29, 31, 37, 41, 43, 47, 53, 59,
2209 61, 67, 71, 73, 79, 83, 89, 97,
2210 101, 103, 107, 109, 113, 127, 131, 137,
2211 139, 149, 151, 157, 163, 167, 173, 179,
2212 181, 191, 193, 197, 199, 211, 223, 227,
2213 229, 233, 239, 241, 251, 257, 263, 269,
2214 271, 277, 281, 283, 293, 307, 311, 313,
2215 317, 331, 337, 347, 349, 353, 359, 367,
2216 373, 379, 383, 389, 397, 401, 409, 419,
2217 421, 431, 433, 439, 443, 449, 457, 461,
2218 463, 467, 479, 487, 491, 499, 503, 509,
2219 521, 523, 541, 547, 557, 563, 569, 571,
2220 577, 587, 593, 599, 601, 607, 613, 617,
2221 619, 631, 641, 643, 647, 653, 659, 661,
2222 673, 677, 683, 691, 701, 709, 719, 727,
2223 733, 739, 743, 751, 757, 761, 769, 773,
2224 787, 797, 809, 811, 821, 823, 827, 829,
2225 839, 853, 857, 859, 863, 877, 881, 883,
2226 887, 907, 911, 919, 929, 937, 941, 947,
2227 953, 967, 971, 977, 983, 991, 997, -103
2228};
2229
2230/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002231 * Small divisors test (X must be positive)
2232 *
2233 * Return values:
2234 * 0: no small factor (possible prime, more tests needed)
2235 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002236 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002237 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002238 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002239static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002240{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002241 int ret = 0;
2242 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002243 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002244
Paul Bakker5121ce52009-01-03 21:22:43 +00002245 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002246 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002247
2248 for( i = 0; small_prime[i] > 0; i++ )
2249 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002250 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002251 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002252
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002253 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002254
2255 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002256 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002257 }
2258
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002259cleanup:
2260 return( ret );
2261}
2262
2263/*
2264 * Miller-Rabin pseudo-primality test (HAC 4.24)
2265 */
Janos Follath72d555d2018-09-03 14:45:23 +01002266static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002267 int (*f_rng)(void *, unsigned char *, size_t),
2268 void *p_rng )
2269{
Pascal Junodb99183d2015-03-11 16:49:45 +01002270 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002271 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002273
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002274 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2275 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002276
Paul Bakker5121ce52009-01-03 21:22:43 +00002277 /*
2278 * W = |X| - 1
2279 * R = W >> lsb( W )
2280 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002281 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2282 s = mbedtls_mpi_lsb( &W );
2283 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2284 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002285
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002286 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002287
Janos Follath72d555d2018-09-03 14:45:23 +01002288 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002289 {
2290 /*
2291 * pick a random A, 1 < A < |X| - 1
2292 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002293 count = 0;
2294 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002295 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002296
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002297 j = mbedtls_mpi_bitlen( &A );
2298 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002299 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002300 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002301 }
2302
2303 if (count++ > 30) {
Jens Wiklanderb2aa9382019-01-17 13:30:57 +01002304 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2305 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002306 }
2307
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002308 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2309 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002310
2311 /*
2312 * A = A^R mod |X|
2313 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002314 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002315
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002316 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2317 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002318 continue;
2319
2320 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002321 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002322 {
2323 /*
2324 * A = A * A mod |X|
2325 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002326 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2327 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002329 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002330 break;
2331
2332 j++;
2333 }
2334
2335 /*
2336 * not prime if A != |X| - 1 or A == 1
2337 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2339 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002340 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002342 break;
2343 }
2344 }
2345
2346cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2348 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002349
2350 return( ret );
2351}
2352
2353/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002354 * Pseudo-primality test: small factors, then Miller-Rabin
2355 */
Darryl Green94759f62018-10-16 15:09:19 +01002356static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002357 int (*f_rng)(void *, unsigned char *, size_t),
2358 void *p_rng )
2359{
2360 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002361 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002362
2363 XX.s = 1;
2364 XX.n = X->n;
2365 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002366
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2368 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2369 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002370
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002371 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002372 return( 0 );
2373
2374 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2375 {
2376 if( ret == 1 )
2377 return( 0 );
2378
2379 return( ret );
2380 }
2381
Janos Follath72d555d2018-09-03 14:45:23 +01002382 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2383}
2384
2385/*
2386 * Pseudo-primality test, error probability 2^-80
2387 */
2388int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2389 int (*f_rng)(void *, unsigned char *, size_t),
2390 void *p_rng )
2391{
2392 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002393}
2394
2395/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002396 * Prime number generation
2397 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002398int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002399 int (*f_rng)(void *, unsigned char *, size_t),
2400 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002401{
Paul Bakker23986e52011-04-24 08:57:21 +00002402 int ret;
2403 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002404 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002405 mbedtls_mpi_uint r;
2406 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002408 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2409 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002410
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002411 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002412
2413 n = BITS_TO_LIMBS( nbits );
2414
Janos Follath72d555d2018-09-03 14:45:23 +01002415 /*
2416 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2417 */
2418 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2419 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2420 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2421
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002422 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002423
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002424 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002425 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002426
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002427 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002428
2429 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002430
2431 if( dh_flag == 0 )
2432 {
Janos Follath72d555d2018-09-03 14:45:23 +01002433 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002434 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002435 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002436 goto cleanup;
2437
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002438 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002439 }
2440 }
2441 else
2442 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002443 /*
2444 * An necessary condition for Y and X = 2Y + 1 to be prime
2445 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2446 * Make sure it is satisfied, while keeping X = 3 mod 4
2447 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002448
2449 X->p[0] |= 2;
2450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002451 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002452 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002453 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002454 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002455 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002456
2457 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002458 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2459 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002460
2461 while( 1 )
2462 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002463 /*
2464 * First, check small factors for X and Y
2465 * before doing Miller-Rabin on any of them
2466 */
2467 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2468 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002469 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2470 == 0 &&
2471 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2472 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002473 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002474 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002475 }
2476
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002477 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002478 goto cleanup;
2479
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002480 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002481 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002482 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2483 * so up Y by 6 and X by 12.
2484 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002485 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2486 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002487 }
2488 }
2489
2490cleanup:
2491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002492 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002493
2494 return( ret );
2495}
2496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002497#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002499#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002500
Paul Bakker23986e52011-04-24 08:57:21 +00002501#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002502
2503static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2504{
2505 { 693, 609, 21 },
2506 { 1764, 868, 28 },
2507 { 768454923, 542167814, 1 }
2508};
2509
Paul Bakker5121ce52009-01-03 21:22:43 +00002510/*
2511 * Checkup routine
2512 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002513int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002514{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002515 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002516 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002517
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002518 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2519 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002520
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002521 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002522 "EFE021C2645FD1DC586E69184AF4A31E" \
2523 "D5F53E93B5F123FA41680867BA110131" \
2524 "944FE7952E2517337780CB0DB80E61AA" \
2525 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2526
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002527 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002528 "B2E7EFD37075B9F03FF989C7C5051C20" \
2529 "34D2A323810251127E7BF8625A4F49A5" \
2530 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2531 "5B5C25763222FEFCCFC38B832366C29E" ) );
2532
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002533 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002534 "0066A198186C18C10B2F5ED9B522752A" \
2535 "9830B69916E535C8F047518A889A43A5" \
2536 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2537
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002538 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002539
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002540 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002541 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2542 "9E857EA95A03512E2BAE7391688D264A" \
2543 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2544 "8001B72E848A38CAE1C65F78E56ABDEF" \
2545 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2546 "ECF677152EF804370C1A305CAF3B5BF1" \
2547 "30879B56C61DE584A0F53A2447A51E" ) );
2548
2549 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002550 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002552 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002553 {
2554 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002555 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002556
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002557 ret = 1;
2558 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002559 }
2560
2561 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002563
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002564 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002565
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002566 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002567 "256567336059E52CAE22925474705F39A94" ) );
2568
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002569 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002570 "6613F26162223DF488E9CD48CC132C7A" \
2571 "0AC93C701B001B092E4E5B9F73BCD27B" \
2572 "9EE50D0657C77F374E903CDFA4C642" ) );
2573
2574 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002575 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002576
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002577 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2578 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002579 {
2580 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002581 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002582
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002583 ret = 1;
2584 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002585 }
2586
2587 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002588 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002589
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002590 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002591
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002592 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002593 "36E139AEA55215609D2816998ED020BB" \
2594 "BD96C37890F65171D948E9BC7CBAA4D9" \
2595 "325D24D6A3C12710F10A09FA08AB87" ) );
2596
2597 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002598 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002599
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002600 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002601 {
2602 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002603 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002604
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002605 ret = 1;
2606 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002607 }
2608
2609 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002610 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002612 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002613
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002614 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002615 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2616 "C3DBA76456363A10869622EAC2DD84EC" \
2617 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2618
2619 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002620 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002622 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002623 {
2624 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002625 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002626
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002627 ret = 1;
2628 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002629 }
2630
2631 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002632 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002633
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002634 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002635 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002636
Paul Bakker66d5d072014-06-17 16:39:18 +02002637 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002638 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002639 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2640 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002641
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002642 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002643
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002644 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002645 {
2646 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002647 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002648
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002649 ret = 1;
2650 goto cleanup;
2651 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002652 }
2653
2654 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002655 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002656
Paul Bakker5121ce52009-01-03 21:22:43 +00002657cleanup:
2658
2659 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002660 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002661
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002662 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2663 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002664
2665 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002666 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002667
2668 return( ret );
2669}
2670
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002671#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002672
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002673#endif /* MBEDTLS_BIGNUM_C */