blob: aa19b0c1c6696544b303b85b91e4e4f756e8efb4 [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 Peskined108d072020-06-04 15:00:49 +02001108 * Helper for mbedtls_mpi subtraction:
1109 * d -= s where d and s have the same size and d >= s.
Paul Bakker5121ce52009-01-03 21:22:43 +00001110 */
Gilles Peskined6496af2020-06-04 15:01:32 +02001111static void mpi_sub_hlp( size_t n,
1112 const mbedtls_mpi_uint *s,
1113 mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001114{
Paul Bakker23986e52011-04-24 08:57:21 +00001115 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001116 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001117
1118 for( i = c = 0; i < n; i++, s++, d++ )
1119 {
1120 z = ( *d < c ); *d -= c;
1121 c = ( *d < *s ) + z; *d -= *s;
1122 }
1123
1124 while( c != 0 )
1125 {
1126 z = ( *d < c ); *d -= c;
1127 c = z; i++; d++;
1128 }
1129}
1130
1131/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001132 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001133 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001134int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001135{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001136 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001137 int ret;
1138 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001139
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001140 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1141 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001142
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001143 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001144
1145 if( X == B )
1146 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001147 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001148 B = &TB;
1149 }
1150
1151 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001152 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001153
Paul Bakker1ef7a532009-06-20 10:50:55 +00001154 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001155 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001156 */
1157 X->s = 1;
1158
Paul Bakker5121ce52009-01-03 21:22:43 +00001159 ret = 0;
1160
Paul Bakker23986e52011-04-24 08:57:21 +00001161 for( n = B->n; n > 0; n-- )
1162 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001163 break;
1164
Paul Bakker23986e52011-04-24 08:57:21 +00001165 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001166
1167cleanup:
1168
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001169 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001170
1171 return( ret );
1172}
1173
1174/*
1175 * Signed addition: X = A + B
1176 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001177int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001178{
1179 int ret, s = A->s;
1180
1181 if( A->s * B->s < 0 )
1182 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001183 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001184 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001185 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001186 X->s = s;
1187 }
1188 else
1189 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001190 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001191 X->s = -s;
1192 }
1193 }
1194 else
1195 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001196 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001197 X->s = s;
1198 }
1199
1200cleanup:
1201
1202 return( ret );
1203}
1204
1205/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001206 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001207 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001208int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001209{
1210 int ret, s = A->s;
1211
1212 if( A->s * B->s > 0 )
1213 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001214 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001215 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001216 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001217 X->s = s;
1218 }
1219 else
1220 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001221 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001222 X->s = -s;
1223 }
1224 }
1225 else
1226 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001227 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001228 X->s = s;
1229 }
1230
1231cleanup:
1232
1233 return( ret );
1234}
1235
1236/*
1237 * Signed addition: X = A + b
1238 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001239int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001240{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001241 mbedtls_mpi _B;
1242 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001243
1244 p[0] = ( b < 0 ) ? -b : b;
1245 _B.s = ( b < 0 ) ? -1 : 1;
1246 _B.n = 1;
1247 _B.p = p;
1248
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001249 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001250}
1251
1252/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001253 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001254 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001255int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001256{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001257 mbedtls_mpi _B;
1258 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001259
1260 p[0] = ( b < 0 ) ? -b : b;
1261 _B.s = ( b < 0 ) ? -1 : 1;
1262 _B.n = 1;
1263 _B.p = p;
1264
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001265 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001266}
1267
1268/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001269 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001270 */
1271static
1272#if defined(__APPLE__) && defined(__arm__)
1273/*
1274 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1275 * appears to need this to prevent bad ARM code generation at -O3.
1276 */
1277__attribute__ ((noinline))
1278#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001279void 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 +00001280{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001281 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001282
1283#if defined(MULADDC_HUIT)
1284 for( ; i >= 8; i -= 8 )
1285 {
1286 MULADDC_INIT
1287 MULADDC_HUIT
1288 MULADDC_STOP
1289 }
1290
1291 for( ; i > 0; i-- )
1292 {
1293 MULADDC_INIT
1294 MULADDC_CORE
1295 MULADDC_STOP
1296 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001297#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001298 for( ; i >= 16; i -= 16 )
1299 {
1300 MULADDC_INIT
1301 MULADDC_CORE MULADDC_CORE
1302 MULADDC_CORE MULADDC_CORE
1303 MULADDC_CORE MULADDC_CORE
1304 MULADDC_CORE MULADDC_CORE
1305
1306 MULADDC_CORE MULADDC_CORE
1307 MULADDC_CORE MULADDC_CORE
1308 MULADDC_CORE MULADDC_CORE
1309 MULADDC_CORE MULADDC_CORE
1310 MULADDC_STOP
1311 }
1312
1313 for( ; i >= 8; i -= 8 )
1314 {
1315 MULADDC_INIT
1316 MULADDC_CORE MULADDC_CORE
1317 MULADDC_CORE MULADDC_CORE
1318
1319 MULADDC_CORE MULADDC_CORE
1320 MULADDC_CORE MULADDC_CORE
1321 MULADDC_STOP
1322 }
1323
1324 for( ; i > 0; i-- )
1325 {
1326 MULADDC_INIT
1327 MULADDC_CORE
1328 MULADDC_STOP
1329 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001330#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001331
1332 t++;
1333
1334 do {
1335 *d += c; c = ( *d < c ); d++;
1336 }
1337 while( c != 0 );
1338}
1339
1340/*
1341 * Baseline multiplication: X = A * B (HAC 14.12)
1342 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001343int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001344{
Paul Bakker23986e52011-04-24 08:57:21 +00001345 int ret;
1346 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001347 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001349 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001350
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001351 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1352 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001353
Paul Bakker23986e52011-04-24 08:57:21 +00001354 for( i = A->n; i > 0; i-- )
1355 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001356 break;
1357
Paul Bakker23986e52011-04-24 08:57:21 +00001358 for( j = B->n; j > 0; j-- )
1359 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001360 break;
1361
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001362 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1363 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001364
Paul Bakker23986e52011-04-24 08:57:21 +00001365 for( i++; j > 0; j-- )
1366 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001367
1368 X->s = A->s * B->s;
1369
1370cleanup:
1371
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001373
1374 return( ret );
1375}
1376
1377/*
1378 * Baseline multiplication: X = A * b
1379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001380int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001381{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001382 mbedtls_mpi _B;
1383 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001384
1385 _B.s = 1;
1386 _B.n = 1;
1387 _B.p = p;
1388 p[0] = b;
1389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001391}
1392
1393/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001394 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1395 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001396 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001397static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1398 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001399{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001400#if defined(MBEDTLS_HAVE_UDBL)
1401 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001402#else
Simon Butcher9803d072016-01-03 00:24:34 +00001403 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1404 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001405 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1406 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001407 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001408#endif
1409
Simon Butcher15b15d12015-11-26 19:35:03 +00001410 /*
1411 * Check for overflow
1412 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001413 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001414 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001415 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001416
Simon Butcherf5ba0452015-12-27 23:01:55 +00001417 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001418 }
1419
1420#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001421 dividend = (mbedtls_t_udbl) u1 << biL;
1422 dividend |= (mbedtls_t_udbl) u0;
1423 quotient = dividend / d;
1424 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1425 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1426
1427 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001428 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001429
1430 return (mbedtls_mpi_uint) quotient;
1431#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001432
1433 /*
1434 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1435 * Vol. 2 - Seminumerical Algorithms, Knuth
1436 */
1437
1438 /*
1439 * Normalize the divisor, d, and dividend, u0, u1
1440 */
1441 s = mbedtls_clz( d );
1442 d = d << s;
1443
1444 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001445 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001446 u0 = u0 << s;
1447
1448 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001449 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001450
1451 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001452 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001453
1454 /*
1455 * Find the first quotient and remainder
1456 */
1457 q1 = u1 / d1;
1458 r0 = u1 - d1 * q1;
1459
1460 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1461 {
1462 q1 -= 1;
1463 r0 += d1;
1464
1465 if ( r0 >= radix ) break;
1466 }
1467
Simon Butcherf5ba0452015-12-27 23:01:55 +00001468 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001469 q0 = rAX / d1;
1470 r0 = rAX - q0 * d1;
1471
1472 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1473 {
1474 q0 -= 1;
1475 r0 += d1;
1476
1477 if ( r0 >= radix ) break;
1478 }
1479
1480 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001481 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001482
1483 quotient = q1 * radix + q0;
1484
1485 return quotient;
1486#endif
1487}
1488
1489/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001490 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001491 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001492int 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 +00001493{
Paul Bakker23986e52011-04-24 08:57:21 +00001494 int ret;
1495 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001496 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001497
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001498 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1499 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001500
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001501 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1502 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001504 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001505 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1507 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001508 return( 0 );
1509 }
1510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1512 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001513 X.s = Y.s = 1;
1514
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001515 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1516 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1517 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1518 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001519
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001520 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001521 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001522 {
1523 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001524 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1525 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001526 }
1527 else k = 0;
1528
1529 n = X.n - 1;
1530 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001531 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001532
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001533 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001534 {
1535 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001536 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001537 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001538 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001539
1540 for( i = n; i > t ; i-- )
1541 {
1542 if( X.p[i] >= Y.p[t] )
1543 Z.p[i - t - 1] = ~0;
1544 else
1545 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001546 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1547 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001548 }
1549
1550 Z.p[i - t - 1]++;
1551 do
1552 {
1553 Z.p[i - t - 1]--;
1554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001555 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001556 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001557 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001558 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001559
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001560 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001561 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1562 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001563 T2.p[2] = X.p[i];
1564 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001565 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001566
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001567 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1568 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1569 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001570
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001571 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001572 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001573 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1574 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1575 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001576 Z.p[i - t - 1]--;
1577 }
1578 }
1579
1580 if( Q != NULL )
1581 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001582 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001583 Q->s = A->s * B->s;
1584 }
1585
1586 if( R != NULL )
1587 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001588 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001589 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001590 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001591
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001592 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001593 R->s = 1;
1594 }
1595
1596cleanup:
1597
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001598 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1599 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001600
1601 return( ret );
1602}
1603
1604/*
1605 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001606 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001607int 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 +00001608{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001609 mbedtls_mpi _B;
1610 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001611
1612 p[0] = ( b < 0 ) ? -b : b;
1613 _B.s = ( b < 0 ) ? -1 : 1;
1614 _B.n = 1;
1615 _B.p = p;
1616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001617 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001618}
1619
1620/*
1621 * Modulo: R = A mod B
1622 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001623int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001624{
1625 int ret;
1626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001627 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1628 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001629
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001630 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001631
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001632 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1633 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001635 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1636 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001637
1638cleanup:
1639
1640 return( ret );
1641}
1642
1643/*
1644 * Modulo: r = A mod b
1645 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001646int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001647{
Paul Bakker23986e52011-04-24 08:57:21 +00001648 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001649 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001650
1651 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001652 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001653
1654 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001655 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001656
1657 /*
1658 * handle trivial cases
1659 */
1660 if( b == 1 )
1661 {
1662 *r = 0;
1663 return( 0 );
1664 }
1665
1666 if( b == 2 )
1667 {
1668 *r = A->p[0] & 1;
1669 return( 0 );
1670 }
1671
1672 /*
1673 * general case
1674 */
Paul Bakker23986e52011-04-24 08:57:21 +00001675 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001676 {
Paul Bakker23986e52011-04-24 08:57:21 +00001677 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001678 y = ( y << biH ) | ( x >> biH );
1679 z = y / b;
1680 y -= z * b;
1681
1682 x <<= biH;
1683 y = ( y << biH ) | ( x >> biH );
1684 z = y / b;
1685 y -= z * b;
1686 }
1687
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001688 /*
1689 * If A is negative, then the current y represents a negative value.
1690 * Flipping it to the positive side.
1691 */
1692 if( A->s < 0 && y != 0 )
1693 y = b - y;
1694
Paul Bakker5121ce52009-01-03 21:22:43 +00001695 *r = y;
1696
1697 return( 0 );
1698}
1699
1700/*
1701 * Fast Montgomery initialization (thanks to Tom St Denis)
1702 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001703static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001704{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001705 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001706 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001707
1708 x = m0;
1709 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001710
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001711 for( i = biL; i >= 8; i /= 2 )
1712 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001713
1714 *mm = ~x + 1;
1715}
1716
Gilles Peskined108d072020-06-04 15:00:49 +02001717/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1718 *
1719 * \param[in,out] A One of the numbers to multiply.
1720 * It must have at least one more limb than N
1721 * (A->n >= N->n + 1).
1722 * On successful completion, A contains the result of
1723 * the multiplication A * B * R^-1 mod N where
1724 * R = (2^ciL)^n.
1725 * \param[in] B One of the numbers to multiply.
1726 * It must be nonzero and must not have more limbs than N
1727 * (B->n <= N->n).
1728 * \param[in] N The modulo. N must be odd.
1729 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1730 * This is -N^-1 mod 2^ciL.
1731 * \param[in,out] T A bignum for temporary storage.
1732 * It must be at least twice the limb size of N plus 2
1733 * (T->n >= 2 * (N->n + 1)).
1734 * Its initial content is unused and
1735 * its final content is indeterminate.
1736 * Note that unlike the usual convention in the library
1737 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00001738 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001739static 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 +02001740 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001741{
Paul Bakker23986e52011-04-24 08:57:21 +00001742 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001743 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001744
1745 memset( T->p, 0, T->n * ciL );
1746
1747 d = T->p;
1748 n = N->n;
1749 m = ( B->n < n ) ? B->n : n;
1750
1751 for( i = 0; i < n; i++ )
1752 {
1753 /*
1754 * T = (T + u0*B + u1*N) / 2^biL
1755 */
1756 u0 = A->p[i];
1757 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1758
1759 mpi_mul_hlp( m, B->p, d, u0 );
1760 mpi_mul_hlp( n, N->p, d, u1 );
1761
1762 *d++ = u0; d[n + 1] = 0;
1763 }
1764
Paul Bakker66d5d072014-06-17 16:39:18 +02001765 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001766
Gilles Peskined108d072020-06-04 15:00:49 +02001767 /* If A >= N then A -= N. Do the subtraction unconditionally to prevent
Gilles Peskine7ff812e2020-06-04 21:05:24 +02001768 * timing attacks. */
1769 /* Set d to A + (2^biL)^n - N. */
1770 d[n] += 1;
1771 mpi_sub_hlp( n, N->p, d );
1772 /* Now d - (2^biL)^n = A - N so d >= (2^biL)^n iff A >= N.
1773 * So we want to copy the result of the subtraction iff d->p[n] != 0.
1774 * Note that d->p[n] is either 0 or 1 since A - N <= N <= (2^biL)^n. */
Gilles Peskineea9ba772020-06-05 10:48:25 +02001775 mpi_safe_cond_assign( n + 1, A->p, d, (unsigned char) d[n] );
Gilles Peskine7ff812e2020-06-04 21:05:24 +02001776 A->p[n] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001777}
1778
1779/*
1780 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskined108d072020-06-04 15:00:49 +02001781 *
1782 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001783 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001784static 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 +00001785{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001786 mbedtls_mpi_uint z = 1;
1787 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001788
Paul Bakker8ddb6452013-02-27 14:56:33 +01001789 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001790 U.p = &z;
1791
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001792 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001793}
1794
1795/*
1796 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1797 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001798int 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 +00001799{
Paul Bakker23986e52011-04-24 08:57:21 +00001800 int ret;
1801 size_t wbits, wsize, one = 1;
1802 size_t i, j, nblimbs;
1803 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001804 mbedtls_mpi_uint ei, mm, state;
1805 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001806 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001807
Hanno Becker930ec7d2018-03-09 10:48:00 +00001808 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001809 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001810
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001811 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1812 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001813
1814 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001815 * Init temps and window size
1816 */
1817 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001818 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1819 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001820 memset( W, 0, sizeof( W ) );
1821
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001822 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001823
1824 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1825 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1826
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001827#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001828 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1829 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001830#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001831
Paul Bakker5121ce52009-01-03 21:22:43 +00001832 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001833 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1834 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1835 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001836
1837 /*
Paul Bakker50546922012-05-19 08:40:49 +00001838 * Compensate for negative A (and correct at the end)
1839 */
1840 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001841 if( neg )
1842 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001843 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001844 Apos.s = 1;
1845 A = &Apos;
1846 }
1847
1848 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001849 * If 1st call, pre-compute R^2 mod N
1850 */
1851 if( _RR == NULL || _RR->p == NULL )
1852 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001853 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1854 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1855 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001856
1857 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001858 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001859 }
1860 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001861 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001862
1863 /*
1864 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1865 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001866 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1867 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001868 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001869 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001870
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001871 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001872
1873 /*
1874 * X = R^2 * R^-1 mod N = R mod N
1875 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001876 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001877 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001878
1879 if( wsize > 1 )
1880 {
1881 /*
1882 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1883 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001884 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001885
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001886 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1887 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001888
1889 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001890 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001891
Paul Bakker5121ce52009-01-03 21:22:43 +00001892 /*
1893 * W[i] = W[i - 1] * W[1]
1894 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001895 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001896 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001897 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1898 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001899
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001900 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001901 }
1902 }
1903
1904 nblimbs = E->n;
1905 bufsize = 0;
1906 nbits = 0;
1907 wbits = 0;
1908 state = 0;
1909
1910 while( 1 )
1911 {
1912 if( bufsize == 0 )
1913 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001914 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001915 break;
1916
Paul Bakker0d7702c2013-10-29 16:18:35 +01001917 nblimbs--;
1918
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001919 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001920 }
1921
1922 bufsize--;
1923
1924 ei = (E->p[nblimbs] >> bufsize) & 1;
1925
1926 /*
1927 * skip leading 0s
1928 */
1929 if( ei == 0 && state == 0 )
1930 continue;
1931
1932 if( ei == 0 && state == 1 )
1933 {
1934 /*
1935 * out of window, square X
1936 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001937 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001938 continue;
1939 }
1940
1941 /*
1942 * add ei to current window
1943 */
1944 state = 2;
1945
1946 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001947 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001948
1949 if( nbits == wsize )
1950 {
1951 /*
1952 * X = X^wsize R^-1 mod N
1953 */
1954 for( i = 0; i < wsize; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001955 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956
1957 /*
1958 * X = X * W[wbits] R^-1 mod N
1959 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001960 mpi_montmul( X, &W[wbits], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001961
1962 state--;
1963 nbits = 0;
1964 wbits = 0;
1965 }
1966 }
1967
1968 /*
1969 * process the remaining bits
1970 */
1971 for( i = 0; i < nbits; i++ )
1972 {
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001973 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001974
1975 wbits <<= 1;
1976
Paul Bakker66d5d072014-06-17 16:39:18 +02001977 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001978 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001979 }
1980
1981 /*
1982 * X = A^E * R * R^-1 mod N = A^E mod N
1983 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001984 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001985
Hanno Beckera4af1c42017-04-18 09:07:45 +01001986 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001987 {
1988 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001989 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001990 }
1991
Paul Bakker5121ce52009-01-03 21:22:43 +00001992cleanup:
1993
Paul Bakker66d5d072014-06-17 16:39:18 +02001994 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001995 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001996
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001997 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001998
Paul Bakker75a28602014-03-31 12:08:17 +02001999 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002000 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002001
2002 return( ret );
2003}
2004
Paul Bakker5121ce52009-01-03 21:22:43 +00002005/*
2006 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2007 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002008int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002009{
Paul Bakker23986e52011-04-24 08:57:21 +00002010 int ret;
2011 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002012 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002013
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002014 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002015
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2017 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002018
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002019 lz = mbedtls_mpi_lsb( &TA );
2020 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002021
Paul Bakker66d5d072014-06-17 16:39:18 +02002022 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002023 lz = lzt;
2024
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002025 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2026 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002027
Paul Bakker5121ce52009-01-03 21:22:43 +00002028 TA.s = TB.s = 1;
2029
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002030 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002031 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002032 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2033 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002034
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002035 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002036 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002037 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2038 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002039 }
2040 else
2041 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002042 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2043 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002044 }
2045 }
2046
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002047 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2048 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002049
2050cleanup:
2051
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002053
2054 return( ret );
2055}
2056
Paul Bakker33dc46b2014-04-30 16:11:39 +02002057/*
2058 * Fill X with size bytes of random.
2059 *
2060 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002061 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002062 * deterministic, eg for tests).
2063 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002064int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002065 int (*f_rng)(void *, unsigned char *, size_t),
2066 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002067{
Paul Bakker23986e52011-04-24 08:57:21 +00002068 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002069 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02002070
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002071 if( size > MBEDTLS_MPI_MAX_SIZE )
2072 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002073
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002074 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2075 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002076
2077cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01002078 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002079 return( ret );
2080}
2081
Paul Bakker5121ce52009-01-03 21:22:43 +00002082/*
2083 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2084 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002085int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002086{
2087 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002088 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002089
Hanno Becker4bcb4912017-04-18 15:49:39 +01002090 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002091 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002092
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002093 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2094 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2095 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002096
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002097 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002098
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002099 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002100 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002101 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002102 goto cleanup;
2103 }
2104
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002105 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2106 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2107 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2108 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002110 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2111 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2112 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2113 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002114
2115 do
2116 {
2117 while( ( TU.p[0] & 1 ) == 0 )
2118 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002119 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002120
2121 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2122 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002123 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2124 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002125 }
2126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002127 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2128 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002129 }
2130
2131 while( ( TV.p[0] & 1 ) == 0 )
2132 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002133 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002134
2135 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2136 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002137 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2138 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002139 }
2140
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002141 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2142 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002143 }
2144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002146 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002147 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2148 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2149 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002150 }
2151 else
2152 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002153 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2154 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2155 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002156 }
2157 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002158 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2161 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002162
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002163 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2164 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002165
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002166 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002167
2168cleanup:
2169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002170 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2171 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2172 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002173
2174 return( ret );
2175}
2176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002178
Paul Bakker5121ce52009-01-03 21:22:43 +00002179static const int small_prime[] =
2180{
2181 3, 5, 7, 11, 13, 17, 19, 23,
2182 29, 31, 37, 41, 43, 47, 53, 59,
2183 61, 67, 71, 73, 79, 83, 89, 97,
2184 101, 103, 107, 109, 113, 127, 131, 137,
2185 139, 149, 151, 157, 163, 167, 173, 179,
2186 181, 191, 193, 197, 199, 211, 223, 227,
2187 229, 233, 239, 241, 251, 257, 263, 269,
2188 271, 277, 281, 283, 293, 307, 311, 313,
2189 317, 331, 337, 347, 349, 353, 359, 367,
2190 373, 379, 383, 389, 397, 401, 409, 419,
2191 421, 431, 433, 439, 443, 449, 457, 461,
2192 463, 467, 479, 487, 491, 499, 503, 509,
2193 521, 523, 541, 547, 557, 563, 569, 571,
2194 577, 587, 593, 599, 601, 607, 613, 617,
2195 619, 631, 641, 643, 647, 653, 659, 661,
2196 673, 677, 683, 691, 701, 709, 719, 727,
2197 733, 739, 743, 751, 757, 761, 769, 773,
2198 787, 797, 809, 811, 821, 823, 827, 829,
2199 839, 853, 857, 859, 863, 877, 881, 883,
2200 887, 907, 911, 919, 929, 937, 941, 947,
2201 953, 967, 971, 977, 983, 991, 997, -103
2202};
2203
2204/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002205 * Small divisors test (X must be positive)
2206 *
2207 * Return values:
2208 * 0: no small factor (possible prime, more tests needed)
2209 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002210 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002211 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002212 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002213static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002214{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002215 int ret = 0;
2216 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002217 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002218
Paul Bakker5121ce52009-01-03 21:22:43 +00002219 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002220 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002221
2222 for( i = 0; small_prime[i] > 0; i++ )
2223 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002224 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002225 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002227 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002228
2229 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002230 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002231 }
2232
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002233cleanup:
2234 return( ret );
2235}
2236
2237/*
2238 * Miller-Rabin pseudo-primality test (HAC 4.24)
2239 */
Janos Follath72d555d2018-09-03 14:45:23 +01002240static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002241 int (*f_rng)(void *, unsigned char *, size_t),
2242 void *p_rng )
2243{
Pascal Junodb99183d2015-03-11 16:49:45 +01002244 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002245 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002246 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002247
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002248 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2249 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002250
Paul Bakker5121ce52009-01-03 21:22:43 +00002251 /*
2252 * W = |X| - 1
2253 * R = W >> lsb( W )
2254 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002255 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2256 s = mbedtls_mpi_lsb( &W );
2257 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2258 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002259
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002260 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002261
Janos Follath72d555d2018-09-03 14:45:23 +01002262 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002263 {
2264 /*
2265 * pick a random A, 1 < A < |X| - 1
2266 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002267 count = 0;
2268 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002269 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002270
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002271 j = mbedtls_mpi_bitlen( &A );
2272 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002273 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002274 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002275 }
2276
2277 if (count++ > 30) {
Jens Wiklanderb2aa9382019-01-17 13:30:57 +01002278 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2279 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002280 }
2281
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002282 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2283 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002284
2285 /*
2286 * A = A^R mod |X|
2287 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002289
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002290 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2291 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002292 continue;
2293
2294 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002295 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002296 {
2297 /*
2298 * A = A * A mod |X|
2299 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002300 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2301 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002302
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002303 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002304 break;
2305
2306 j++;
2307 }
2308
2309 /*
2310 * not prime if A != |X| - 1 or A == 1
2311 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002312 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2313 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002314 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002315 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002316 break;
2317 }
2318 }
2319
2320cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002321 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2322 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002323
2324 return( ret );
2325}
2326
2327/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002328 * Pseudo-primality test: small factors, then Miller-Rabin
2329 */
Darryl Green94759f62018-10-16 15:09:19 +01002330static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002331 int (*f_rng)(void *, unsigned char *, size_t),
2332 void *p_rng )
2333{
2334 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002336
2337 XX.s = 1;
2338 XX.n = X->n;
2339 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2342 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2343 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002345 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002346 return( 0 );
2347
2348 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2349 {
2350 if( ret == 1 )
2351 return( 0 );
2352
2353 return( ret );
2354 }
2355
Janos Follath72d555d2018-09-03 14:45:23 +01002356 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2357}
2358
2359/*
2360 * Pseudo-primality test, error probability 2^-80
2361 */
2362int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2363 int (*f_rng)(void *, unsigned char *, size_t),
2364 void *p_rng )
2365{
2366 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002367}
2368
2369/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002370 * Prime number generation
2371 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002372int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002373 int (*f_rng)(void *, unsigned char *, size_t),
2374 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002375{
Paul Bakker23986e52011-04-24 08:57:21 +00002376 int ret;
2377 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002378 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002379 mbedtls_mpi_uint r;
2380 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002381
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002382 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2383 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002386
2387 n = BITS_TO_LIMBS( nbits );
2388
Janos Follath72d555d2018-09-03 14:45:23 +01002389 /*
2390 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2391 */
2392 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2393 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2394 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002397
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002398 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002399 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002400
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002401 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002402
2403 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002404
2405 if( dh_flag == 0 )
2406 {
Janos Follath72d555d2018-09-03 14:45:23 +01002407 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002408 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002409 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002410 goto cleanup;
2411
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002412 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002413 }
2414 }
2415 else
2416 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002417 /*
2418 * An necessary condition for Y and X = 2Y + 1 to be prime
2419 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2420 * Make sure it is satisfied, while keeping X = 3 mod 4
2421 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002422
2423 X->p[0] |= 2;
2424
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002425 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002426 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002427 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002428 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002429 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002430
2431 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002432 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2433 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002434
2435 while( 1 )
2436 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002437 /*
2438 * First, check small factors for X and Y
2439 * before doing Miller-Rabin on any of them
2440 */
2441 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2442 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002443 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2444 == 0 &&
2445 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2446 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002447 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002448 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002449 }
2450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002451 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002452 goto cleanup;
2453
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002454 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002455 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002456 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2457 * so up Y by 6 and X by 12.
2458 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002459 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2460 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002461 }
2462 }
2463
2464cleanup:
2465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002466 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002467
2468 return( ret );
2469}
2470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002471#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002474
Paul Bakker23986e52011-04-24 08:57:21 +00002475#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002476
2477static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2478{
2479 { 693, 609, 21 },
2480 { 1764, 868, 28 },
2481 { 768454923, 542167814, 1 }
2482};
2483
Paul Bakker5121ce52009-01-03 21:22:43 +00002484/*
2485 * Checkup routine
2486 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002487int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002488{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002489 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002490 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002492 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2493 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002494
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002495 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002496 "EFE021C2645FD1DC586E69184AF4A31E" \
2497 "D5F53E93B5F123FA41680867BA110131" \
2498 "944FE7952E2517337780CB0DB80E61AA" \
2499 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2500
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002501 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002502 "B2E7EFD37075B9F03FF989C7C5051C20" \
2503 "34D2A323810251127E7BF8625A4F49A5" \
2504 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2505 "5B5C25763222FEFCCFC38B832366C29E" ) );
2506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002507 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002508 "0066A198186C18C10B2F5ED9B522752A" \
2509 "9830B69916E535C8F047518A889A43A5" \
2510 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2511
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002512 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002514 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002515 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2516 "9E857EA95A03512E2BAE7391688D264A" \
2517 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2518 "8001B72E848A38CAE1C65F78E56ABDEF" \
2519 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2520 "ECF677152EF804370C1A305CAF3B5BF1" \
2521 "30879B56C61DE584A0F53A2447A51E" ) );
2522
2523 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002524 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002526 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002527 {
2528 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002529 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002530
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002531 ret = 1;
2532 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002533 }
2534
2535 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002536 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002537
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002538 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &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 "256567336059E52CAE22925474705F39A94" ) );
2542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002543 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002544 "6613F26162223DF488E9CD48CC132C7A" \
2545 "0AC93C701B001B092E4E5B9F73BCD27B" \
2546 "9EE50D0657C77F374E903CDFA4C642" ) );
2547
2548 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002549 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002550
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002551 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2552 mbedtls_mpi_cmp_mpi( &Y, &V ) != 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_exp_mod( &X, &A, &E, &N, NULL ) );
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 "36E139AEA55215609D2816998ED020BB" \
2568 "BD96C37890F65171D948E9BC7CBAA4D9" \
2569 "325D24D6A3C12710F10A09FA08AB87" ) );
2570
2571 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002572 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002573
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002574 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002575 {
2576 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002577 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002578
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002579 ret = 1;
2580 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002581 }
2582
2583 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002584 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002585
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002586 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002587
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002588 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002589 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2590 "C3DBA76456363A10869622EAC2DD84EC" \
2591 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2592
2593 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002594 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002595
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002596 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002597 {
2598 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002599 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002600
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002601 ret = 1;
2602 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002603 }
2604
2605 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002606 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002607
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002608 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002609 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002610
Paul Bakker66d5d072014-06-17 16:39:18 +02002611 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002612 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002613 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2614 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002615
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002616 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002617
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002618 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002619 {
2620 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002621 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002622
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002623 ret = 1;
2624 goto cleanup;
2625 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002626 }
2627
2628 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002629 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002630
Paul Bakker5121ce52009-01-03 21:22:43 +00002631cleanup:
2632
2633 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002634 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002636 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2637 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002638
2639 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002640 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002641
2642 return( ret );
2643}
2644
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002645#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002646
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002647#endif /* MBEDTLS_BIGNUM_C */