blob: c6948d6af7f1ff0fe11fbaab559cabc5cffc5c6d [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
1768 * timing attacks. Modify T as a side effect. */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001769 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001770 mpi_sub_hlp( n, N->p, A->p );
1771 else
1772 /* prevent timing attacks */
1773 mpi_sub_hlp( n, A->p, T->p );
1774}
1775
1776/*
1777 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskined108d072020-06-04 15:00:49 +02001778 *
1779 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001780 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001781static 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 +00001782{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001783 mbedtls_mpi_uint z = 1;
1784 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001785
Paul Bakker8ddb6452013-02-27 14:56:33 +01001786 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001787 U.p = &z;
1788
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001789 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001790}
1791
1792/*
1793 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1794 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001795int 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 +00001796{
Paul Bakker23986e52011-04-24 08:57:21 +00001797 int ret;
1798 size_t wbits, wsize, one = 1;
1799 size_t i, j, nblimbs;
1800 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001801 mbedtls_mpi_uint ei, mm, state;
1802 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001803 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001804
Hanno Becker930ec7d2018-03-09 10:48:00 +00001805 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001806 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001807
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001808 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1809 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001810
1811 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001812 * Init temps and window size
1813 */
1814 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001815 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1816 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001817 memset( W, 0, sizeof( W ) );
1818
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001819 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001820
1821 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1822 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1823
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001824#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001825 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1826 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001827#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001828
Paul Bakker5121ce52009-01-03 21:22:43 +00001829 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1831 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1832 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001833
1834 /*
Paul Bakker50546922012-05-19 08:40:49 +00001835 * Compensate for negative A (and correct at the end)
1836 */
1837 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001838 if( neg )
1839 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001840 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001841 Apos.s = 1;
1842 A = &Apos;
1843 }
1844
1845 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001846 * If 1st call, pre-compute R^2 mod N
1847 */
1848 if( _RR == NULL || _RR->p == NULL )
1849 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001850 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1851 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1852 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001853
1854 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001855 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001856 }
1857 else
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 /*
1861 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1862 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001863 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1864 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001865 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001866 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001867
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001868 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001869
1870 /*
1871 * X = R^2 * R^-1 mod N = R mod N
1872 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001873 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001874 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001875
1876 if( wsize > 1 )
1877 {
1878 /*
1879 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1880 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001881 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001882
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001883 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1884 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001885
1886 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001887 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001888
Paul Bakker5121ce52009-01-03 21:22:43 +00001889 /*
1890 * W[i] = W[i - 1] * W[1]
1891 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001892 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001893 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1895 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001896
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001897 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001898 }
1899 }
1900
1901 nblimbs = E->n;
1902 bufsize = 0;
1903 nbits = 0;
1904 wbits = 0;
1905 state = 0;
1906
1907 while( 1 )
1908 {
1909 if( bufsize == 0 )
1910 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001911 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001912 break;
1913
Paul Bakker0d7702c2013-10-29 16:18:35 +01001914 nblimbs--;
1915
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001916 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001917 }
1918
1919 bufsize--;
1920
1921 ei = (E->p[nblimbs] >> bufsize) & 1;
1922
1923 /*
1924 * skip leading 0s
1925 */
1926 if( ei == 0 && state == 0 )
1927 continue;
1928
1929 if( ei == 0 && state == 1 )
1930 {
1931 /*
1932 * out of window, square X
1933 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001934 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001935 continue;
1936 }
1937
1938 /*
1939 * add ei to current window
1940 */
1941 state = 2;
1942
1943 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001944 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
1946 if( nbits == wsize )
1947 {
1948 /*
1949 * X = X^wsize R^-1 mod N
1950 */
1951 for( i = 0; i < wsize; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001952 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001953
1954 /*
1955 * X = X * W[wbits] R^-1 mod N
1956 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001957 mpi_montmul( X, &W[wbits], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001958
1959 state--;
1960 nbits = 0;
1961 wbits = 0;
1962 }
1963 }
1964
1965 /*
1966 * process the remaining bits
1967 */
1968 for( i = 0; i < nbits; i++ )
1969 {
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001970 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001971
1972 wbits <<= 1;
1973
Paul Bakker66d5d072014-06-17 16:39:18 +02001974 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001975 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001976 }
1977
1978 /*
1979 * X = A^E * R * R^-1 mod N = A^E mod N
1980 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001981 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001982
Hanno Beckera4af1c42017-04-18 09:07:45 +01001983 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001984 {
1985 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001986 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001987 }
1988
Paul Bakker5121ce52009-01-03 21:22:43 +00001989cleanup:
1990
Paul Bakker66d5d072014-06-17 16:39:18 +02001991 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001992 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001993
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001994 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001995
Paul Bakker75a28602014-03-31 12:08:17 +02001996 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001997 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001998
1999 return( ret );
2000}
2001
Paul Bakker5121ce52009-01-03 21:22:43 +00002002/*
2003 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2004 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002005int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002006{
Paul Bakker23986e52011-04-24 08:57:21 +00002007 int ret;
2008 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002009 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002010
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002011 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002012
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002013 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2014 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002015
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016 lz = mbedtls_mpi_lsb( &TA );
2017 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002018
Paul Bakker66d5d072014-06-17 16:39:18 +02002019 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002020 lz = lzt;
2021
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002022 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2023 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002024
Paul Bakker5121ce52009-01-03 21:22:43 +00002025 TA.s = TB.s = 1;
2026
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002027 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002028 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2030 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002032 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002033 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2035 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002036 }
2037 else
2038 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002039 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2040 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002041 }
2042 }
2043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002044 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2045 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002046
2047cleanup:
2048
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002050
2051 return( ret );
2052}
2053
Paul Bakker33dc46b2014-04-30 16:11:39 +02002054/*
2055 * Fill X with size bytes of random.
2056 *
2057 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002058 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002059 * deterministic, eg for tests).
2060 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002061int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002062 int (*f_rng)(void *, unsigned char *, size_t),
2063 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002064{
Paul Bakker23986e52011-04-24 08:57:21 +00002065 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002066 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02002067
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002068 if( size > MBEDTLS_MPI_MAX_SIZE )
2069 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002070
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002071 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2072 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002073
2074cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01002075 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002076 return( ret );
2077}
2078
Paul Bakker5121ce52009-01-03 21:22:43 +00002079/*
2080 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2081 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002082int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002083{
2084 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002085 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002086
Hanno Becker4bcb4912017-04-18 15:49:39 +01002087 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002088 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002089
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002090 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2091 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2092 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002093
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002094 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002095
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002096 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002097 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002098 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002099 goto cleanup;
2100 }
2101
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002102 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2103 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2104 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2105 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002107 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2108 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2109 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2110 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002111
2112 do
2113 {
2114 while( ( TU.p[0] & 1 ) == 0 )
2115 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002116 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002117
2118 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2119 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002120 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2121 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002122 }
2123
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002124 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2125 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002126 }
2127
2128 while( ( TV.p[0] & 1 ) == 0 )
2129 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002130 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002131
2132 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2133 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002134 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2135 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002136 }
2137
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002138 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2139 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002140 }
2141
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002142 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002143 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002144 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2145 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2146 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002147 }
2148 else
2149 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002150 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2151 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2152 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002153 }
2154 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002155 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002156
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002157 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2158 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2161 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002162
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002163 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002164
2165cleanup:
2166
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002167 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2168 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2169 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002170
2171 return( ret );
2172}
2173
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002174#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002175
Paul Bakker5121ce52009-01-03 21:22:43 +00002176static const int small_prime[] =
2177{
2178 3, 5, 7, 11, 13, 17, 19, 23,
2179 29, 31, 37, 41, 43, 47, 53, 59,
2180 61, 67, 71, 73, 79, 83, 89, 97,
2181 101, 103, 107, 109, 113, 127, 131, 137,
2182 139, 149, 151, 157, 163, 167, 173, 179,
2183 181, 191, 193, 197, 199, 211, 223, 227,
2184 229, 233, 239, 241, 251, 257, 263, 269,
2185 271, 277, 281, 283, 293, 307, 311, 313,
2186 317, 331, 337, 347, 349, 353, 359, 367,
2187 373, 379, 383, 389, 397, 401, 409, 419,
2188 421, 431, 433, 439, 443, 449, 457, 461,
2189 463, 467, 479, 487, 491, 499, 503, 509,
2190 521, 523, 541, 547, 557, 563, 569, 571,
2191 577, 587, 593, 599, 601, 607, 613, 617,
2192 619, 631, 641, 643, 647, 653, 659, 661,
2193 673, 677, 683, 691, 701, 709, 719, 727,
2194 733, 739, 743, 751, 757, 761, 769, 773,
2195 787, 797, 809, 811, 821, 823, 827, 829,
2196 839, 853, 857, 859, 863, 877, 881, 883,
2197 887, 907, 911, 919, 929, 937, 941, 947,
2198 953, 967, 971, 977, 983, 991, 997, -103
2199};
2200
2201/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002202 * Small divisors test (X must be positive)
2203 *
2204 * Return values:
2205 * 0: no small factor (possible prime, more tests needed)
2206 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002207 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002208 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002209 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002210static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002211{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002212 int ret = 0;
2213 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002214 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002215
Paul Bakker5121ce52009-01-03 21:22:43 +00002216 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002217 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002218
2219 for( i = 0; small_prime[i] > 0; i++ )
2220 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002221 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002222 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002223
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002224 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002225
2226 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002227 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002228 }
2229
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002230cleanup:
2231 return( ret );
2232}
2233
2234/*
2235 * Miller-Rabin pseudo-primality test (HAC 4.24)
2236 */
Janos Follath72d555d2018-09-03 14:45:23 +01002237static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002238 int (*f_rng)(void *, unsigned char *, size_t),
2239 void *p_rng )
2240{
Pascal Junodb99183d2015-03-11 16:49:45 +01002241 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002242 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002243 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002244
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002245 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2246 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002247
Paul Bakker5121ce52009-01-03 21:22:43 +00002248 /*
2249 * W = |X| - 1
2250 * R = W >> lsb( W )
2251 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002252 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2253 s = mbedtls_mpi_lsb( &W );
2254 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2255 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002256
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002257 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002258
Janos Follath72d555d2018-09-03 14:45:23 +01002259 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002260 {
2261 /*
2262 * pick a random A, 1 < A < |X| - 1
2263 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002264 count = 0;
2265 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002266 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002267
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002268 j = mbedtls_mpi_bitlen( &A );
2269 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002270 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002271 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002272 }
2273
2274 if (count++ > 30) {
Jens Wiklanderb2aa9382019-01-17 13:30:57 +01002275 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2276 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002277 }
2278
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002279 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2280 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002281
2282 /*
2283 * A = A^R mod |X|
2284 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002285 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002287 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2288 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002289 continue;
2290
2291 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002292 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002293 {
2294 /*
2295 * A = A * A mod |X|
2296 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002297 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2298 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002299
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002300 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002301 break;
2302
2303 j++;
2304 }
2305
2306 /*
2307 * not prime if A != |X| - 1 or A == 1
2308 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002309 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2310 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002311 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002312 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002313 break;
2314 }
2315 }
2316
2317cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002318 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2319 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002320
2321 return( ret );
2322}
2323
2324/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002325 * Pseudo-primality test: small factors, then Miller-Rabin
2326 */
Darryl Green94759f62018-10-16 15:09:19 +01002327static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002328 int (*f_rng)(void *, unsigned char *, size_t),
2329 void *p_rng )
2330{
2331 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002332 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002333
2334 XX.s = 1;
2335 XX.n = X->n;
2336 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2339 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2340 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002343 return( 0 );
2344
2345 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2346 {
2347 if( ret == 1 )
2348 return( 0 );
2349
2350 return( ret );
2351 }
2352
Janos Follath72d555d2018-09-03 14:45:23 +01002353 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2354}
2355
2356/*
2357 * Pseudo-primality test, error probability 2^-80
2358 */
2359int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2360 int (*f_rng)(void *, unsigned char *, size_t),
2361 void *p_rng )
2362{
2363 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002364}
2365
2366/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002367 * Prime number generation
2368 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002369int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002370 int (*f_rng)(void *, unsigned char *, size_t),
2371 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002372{
Paul Bakker23986e52011-04-24 08:57:21 +00002373 int ret;
2374 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002375 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376 mbedtls_mpi_uint r;
2377 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002379 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2380 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002381
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002382 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002383
2384 n = BITS_TO_LIMBS( nbits );
2385
Janos Follath72d555d2018-09-03 14:45:23 +01002386 /*
2387 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2388 */
2389 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2390 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2391 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002393 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002394
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002395 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002396 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002397
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002398 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002399
2400 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002401
2402 if( dh_flag == 0 )
2403 {
Janos Follath72d555d2018-09-03 14:45:23 +01002404 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002405 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002406 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002407 goto cleanup;
2408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002409 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002410 }
2411 }
2412 else
2413 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002414 /*
2415 * An necessary condition for Y and X = 2Y + 1 to be prime
2416 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2417 * Make sure it is satisfied, while keeping X = 3 mod 4
2418 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002419
2420 X->p[0] |= 2;
2421
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002422 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002423 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002424 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002425 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002426 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002427
2428 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002429 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2430 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002431
2432 while( 1 )
2433 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002434 /*
2435 * First, check small factors for X and Y
2436 * before doing Miller-Rabin on any of them
2437 */
2438 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2439 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002440 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2441 == 0 &&
2442 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2443 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002444 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002445 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002446 }
2447
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002448 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002449 goto cleanup;
2450
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002451 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002452 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002453 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2454 * so up Y by 6 and X by 12.
2455 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002456 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2457 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002458 }
2459 }
2460
2461cleanup:
2462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002463 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002464
2465 return( ret );
2466}
2467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002468#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002469
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002470#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002471
Paul Bakker23986e52011-04-24 08:57:21 +00002472#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002473
2474static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2475{
2476 { 693, 609, 21 },
2477 { 1764, 868, 28 },
2478 { 768454923, 542167814, 1 }
2479};
2480
Paul Bakker5121ce52009-01-03 21:22:43 +00002481/*
2482 * Checkup routine
2483 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002484int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002485{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002486 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002487 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002489 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2490 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002492 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002493 "EFE021C2645FD1DC586E69184AF4A31E" \
2494 "D5F53E93B5F123FA41680867BA110131" \
2495 "944FE7952E2517337780CB0DB80E61AA" \
2496 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2497
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002498 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002499 "B2E7EFD37075B9F03FF989C7C5051C20" \
2500 "34D2A323810251127E7BF8625A4F49A5" \
2501 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2502 "5B5C25763222FEFCCFC38B832366C29E" ) );
2503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002504 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002505 "0066A198186C18C10B2F5ED9B522752A" \
2506 "9830B69916E535C8F047518A889A43A5" \
2507 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002509 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002511 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002512 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2513 "9E857EA95A03512E2BAE7391688D264A" \
2514 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2515 "8001B72E848A38CAE1C65F78E56ABDEF" \
2516 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2517 "ECF677152EF804370C1A305CAF3B5BF1" \
2518 "30879B56C61DE584A0F53A2447A51E" ) );
2519
2520 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002521 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002522
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002523 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002524 {
2525 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002526 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002527
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002528 ret = 1;
2529 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002530 }
2531
2532 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002533 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002534
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002535 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002536
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002537 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002538 "256567336059E52CAE22925474705F39A94" ) );
2539
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002540 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002541 "6613F26162223DF488E9CD48CC132C7A" \
2542 "0AC93C701B001B092E4E5B9F73BCD27B" \
2543 "9EE50D0657C77F374E903CDFA4C642" ) );
2544
2545 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002546 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002547
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002548 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2549 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002550 {
2551 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002552 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002553
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002554 ret = 1;
2555 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002556 }
2557
2558 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002559 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002560
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002561 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002562
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002563 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002564 "36E139AEA55215609D2816998ED020BB" \
2565 "BD96C37890F65171D948E9BC7CBAA4D9" \
2566 "325D24D6A3C12710F10A09FA08AB87" ) );
2567
2568 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002569 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002570
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002571 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002572 {
2573 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002574 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002575
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002576 ret = 1;
2577 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002578 }
2579
2580 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002581 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002582
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002583 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002584
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002585 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002586 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2587 "C3DBA76456363A10869622EAC2DD84EC" \
2588 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2589
2590 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002591 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002593 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002594 {
2595 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002596 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002597
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002598 ret = 1;
2599 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002600 }
2601
2602 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002603 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002604
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002605 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002606 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002607
Paul Bakker66d5d072014-06-17 16:39:18 +02002608 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002609 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002610 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2611 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002612
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002613 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002615 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002616 {
2617 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002618 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002619
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002620 ret = 1;
2621 goto cleanup;
2622 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002623 }
2624
2625 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002626 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002627
Paul Bakker5121ce52009-01-03 21:22:43 +00002628cleanup:
2629
2630 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002631 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002632
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002633 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2634 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002635
2636 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002637 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002638
2639 return( ret );
2640}
2641
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002642#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002643
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002644#endif /* MBEDTLS_BIGNUM_C */