blob: 79e267d35c12e5ae07a83f4f6be977986cc94ca9 [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/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100230 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100231 * about whether the assignment was made or not.
232 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100233 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200234int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100235{
236 int ret = 0;
237 size_t i;
238
Pascal Junodb99183d2015-03-11 16:49:45 +0100239 /* make sure assign is 0 or 1 in a time-constant manner */
240 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100241
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200242 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100243
Paul Bakker66d5d072014-06-17 16:39:18 +0200244 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100245
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100246 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200247 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100248
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100249 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200250 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100251
252cleanup:
253 return( ret );
254}
255
256/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100257 * Conditionally swap X and Y, without leaking information
258 * about whether the swap was made or not.
259 * Here it is not ok to simply swap the pointers, which whould lead to
260 * different memory access patterns when X and Y are used afterwards.
261 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200262int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100263{
264 int ret, s;
265 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200266 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100267
268 if( X == Y )
269 return( 0 );
270
Pascal Junodb99183d2015-03-11 16:49:45 +0100271 /* make sure swap is 0 or 1 in a time-constant manner */
272 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100273
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200274 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
275 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100276
277 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200278 X->s = X->s * ( 1 - swap ) + Y->s * swap;
279 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100280
281
282 for( i = 0; i < X->n; i++ )
283 {
284 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200285 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
286 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100287 }
288
289cleanup:
290 return( ret );
291}
292
293/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000294 * Set value from integer
295 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200296int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000297{
298 int ret;
299
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200300 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000301 memset( X->p, 0, X->n * ciL );
302
303 X->p[0] = ( z < 0 ) ? -z : z;
304 X->s = ( z < 0 ) ? -1 : 1;
305
306cleanup:
307
308 return( ret );
309}
310
311/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000312 * Get a specific bit
313 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200314int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000315{
316 if( X->n * biL <= pos )
317 return( 0 );
318
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200319 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000320}
321
Gilles Peskine220cc172018-11-20 16:47:47 +0100322/* Get a specific byte, without range checks. */
323#define GET_BYTE( X, i ) \
324 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
325
Paul Bakker2f5947e2011-05-18 15:47:11 +0000326/*
327 * Set a bit to a specific value of 0 or 1
328 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200329int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000330{
331 int ret = 0;
332 size_t off = pos / biL;
333 size_t idx = pos % biL;
334
335 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200337
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338 if( X->n * biL <= pos )
339 {
340 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200341 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200343 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000344 }
345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200346 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
347 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000348
349cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200350
Paul Bakker2f5947e2011-05-18 15:47:11 +0000351 return( ret );
352}
353
354/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200355 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000356 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200357size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000358{
Paul Bakker23986e52011-04-24 08:57:21 +0000359 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000360
361 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000362 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000363 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
364 return( count );
365
366 return( 0 );
367}
368
369/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000370 * Count leading zero bits in a given integer
371 */
372static size_t mbedtls_clz( const mbedtls_mpi_uint x )
373{
374 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100375 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000376
377 for( j = 0; j < biL; j++ )
378 {
379 if( x & mask ) break;
380
381 mask >>= 1;
382 }
383
384 return j;
385}
386
387/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200388 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000389 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200390size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000391{
Paul Bakker23986e52011-04-24 08:57:21 +0000392 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000393
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200394 if( X->n == 0 )
395 return( 0 );
396
Paul Bakker5121ce52009-01-03 21:22:43 +0000397 for( i = X->n - 1; i > 0; i-- )
398 if( X->p[i] != 0 )
399 break;
400
Simon Butcher15b15d12015-11-26 19:35:03 +0000401 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000402
Paul Bakker23986e52011-04-24 08:57:21 +0000403 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000404}
405
406/*
407 * Return the total size in bytes
408 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000410{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200411 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000412}
413
414/*
415 * Convert an ASCII character to digit value
416 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200417static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000418{
419 *d = 255;
420
421 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
422 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
423 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
424
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200425 if( *d >= (mbedtls_mpi_uint) radix )
426 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000427
428 return( 0 );
429}
430
431/*
432 * Import from an ASCII string
433 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000435{
Paul Bakker23986e52011-04-24 08:57:21 +0000436 int ret;
437 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200438 mbedtls_mpi_uint d;
439 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000440
441 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000443
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200444 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000445
Paul Bakkerff60ee62010-03-16 21:09:09 +0000446 slen = strlen( s );
447
Paul Bakker5121ce52009-01-03 21:22:43 +0000448 if( radix == 16 )
449 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100450 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200451 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
452
Paul Bakkerff60ee62010-03-16 21:09:09 +0000453 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
456 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000457
Paul Bakker23986e52011-04-24 08:57:21 +0000458 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000459 {
Paul Bakker23986e52011-04-24 08:57:21 +0000460 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000461 {
462 X->s = -1;
463 break;
464 }
465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200466 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200467 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000468 }
469 }
470 else
471 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000473
Paul Bakkerff60ee62010-03-16 21:09:09 +0000474 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000475 {
476 if( i == 0 && s[i] == '-' )
477 {
478 X->s = -1;
479 continue;
480 }
481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
483 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000484
485 if( X->s == 1 )
486 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000488 }
489 else
490 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000492 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000493 }
494 }
495
496cleanup:
497
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
500 return( ret );
501}
502
503/*
Ron Eldore6cbfc32018-11-20 14:07:01 +0200504 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000505 */
Ron Eldore6cbfc32018-11-20 14:07:01 +0200506static int mpi_write_hlp( mbedtls_mpi *X, int radix,
507 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000508{
509 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510 mbedtls_mpi_uint r;
Ron Eldore6cbfc32018-11-20 14:07:01 +0200511 size_t length = 0;
512 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000513
Ron Eldore6cbfc32018-11-20 14:07:01 +0200514 do
515 {
516 if( length >= buflen )
517 {
518 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
519 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000520
Ron Eldore6cbfc32018-11-20 14:07:01 +0200521 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
522 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
523 /*
524 * Write the residue in the current position, as an ASCII character.
525 */
526 if( r < 0xA )
527 *(--p_end) = (char)( '0' + r );
528 else
529 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000530
Ron Eldore6cbfc32018-11-20 14:07:01 +0200531 length++;
532 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000533
Ron Eldore6cbfc32018-11-20 14:07:01 +0200534 memmove( *p, p_end, length );
535 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000536
537cleanup:
538
539 return( ret );
540}
541
542/*
543 * Export into an ASCII string
544 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100545int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
546 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000547{
Paul Bakker23986e52011-04-24 08:57:21 +0000548 int ret = 0;
549 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000550 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200551 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000552
553 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200554 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000555
Hanno Beckera277d4c2019-02-04 09:45:07 +0000556 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
557 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
558 * `n`. If radix > 4, this might be a strict
559 * overapproximation of the number of
560 * radix-adic digits needed to present `n`. */
561 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
562 * present `n`. */
563
Janos Follath216e7382019-03-06 13:43:02 +0000564 n += 1; /* Terminating null byte */
Hanno Beckera277d4c2019-02-04 09:45:07 +0000565 n += 1; /* Compensate for the divisions above, which round down `n`
566 * in case it's not even. */
567 n += 1; /* Potential '-'-sign. */
568 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
569 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000570
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100571 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000572 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100573 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200574 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000575 }
576
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100577 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000579
580 if( X->s == -1 )
Hanno Beckereff335d2019-02-01 16:41:30 +0000581 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000582 *p++ = '-';
Hanno Beckereff335d2019-02-01 16:41:30 +0000583 buflen--;
584 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000585
586 if( radix == 16 )
587 {
Paul Bakker23986e52011-04-24 08:57:21 +0000588 int c;
589 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000590
Paul Bakker23986e52011-04-24 08:57:21 +0000591 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000592 {
Paul Bakker23986e52011-04-24 08:57:21 +0000593 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000594 {
Paul Bakker23986e52011-04-24 08:57:21 +0000595 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000596
Paul Bakker6c343d72014-07-10 14:36:19 +0200597 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000598 continue;
599
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000600 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000601 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000602 k = 1;
603 }
604 }
605 }
606 else
607 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000609
610 if( T.s == -1 )
611 T.s = 1;
612
Ron Eldore6cbfc32018-11-20 14:07:01 +0200613 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000614 }
615
616 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100617 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000618
619cleanup:
620
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000622
623 return( ret );
624}
625
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200626#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000627/*
628 * Read X from an opened file
629 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000631{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200632 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000633 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000634 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000635 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000636 * Buffer should have space for (short) label and decimal formatted MPI,
637 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000638 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200639 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000640
641 memset( s, 0, sizeof( s ) );
642 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200643 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000644
645 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000646 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200647 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000648
Hanno Beckerb2034b72017-04-26 11:46:46 +0100649 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
650 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000651
652 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100653 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000654 if( mpi_get_digit( &d, radix, *p ) != 0 )
655 break;
656
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200657 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000658}
659
660/*
661 * Write X into an opened file (or stdout if fout == NULL)
662 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200663int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000664{
Paul Bakker23986e52011-04-24 08:57:21 +0000665 int ret;
666 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000667 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000668 * Buffer should have space for (short) label and decimal formatted MPI,
669 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000670 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000672
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100673 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000674
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100675 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000676
677 if( p == NULL ) p = "";
678
679 plen = strlen( p );
680 slen = strlen( s );
681 s[slen++] = '\r';
682 s[slen++] = '\n';
683
684 if( fout != NULL )
685 {
686 if( fwrite( p, 1, plen, fout ) != plen ||
687 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200688 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000689 }
690 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000692
693cleanup:
694
695 return( ret );
696}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
699/*
700 * Import X from unsigned binary data, big endian
701 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200702int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000703{
Paul Bakker23986e52011-04-24 08:57:21 +0000704 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100705 size_t i, j;
706 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
Hanno Becker073c1992017-10-17 15:17:27 +0100708 /* Ensure that target MPI has exactly the necessary number of limbs */
709 if( X->n != limbs )
710 {
711 mbedtls_mpi_free( X );
712 mbedtls_mpi_init( X );
713 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
714 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000715
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200716 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000717
Hanno Becker073c1992017-10-17 15:17:27 +0100718 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000720
721cleanup:
722
723 return( ret );
724}
725
726/*
727 * Export X into unsigned binary data, big endian
728 */
Gilles Peskine220cc172018-11-20 16:47:47 +0100729int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
730 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000731{
Gilles Peskine220cc172018-11-20 16:47:47 +0100732 size_t stored_bytes = X->n * ciL;
733 size_t bytes_to_copy;
734 unsigned char *p;
735 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000736
Gilles Peskine220cc172018-11-20 16:47:47 +0100737 if( stored_bytes < buflen )
738 {
739 /* There is enough space in the output buffer. Write initial
740 * null bytes and record the position at which to start
741 * writing the significant bytes. In this case, the execution
742 * trace of this function does not depend on the value of the
743 * number. */
744 bytes_to_copy = stored_bytes;
745 p = buf + buflen - stored_bytes;
746 memset( buf, 0, buflen - stored_bytes );
747 }
748 else
749 {
750 /* The output buffer is smaller than the allocated size of X.
751 * However X may fit if its leading bytes are zero. */
752 bytes_to_copy = buflen;
753 p = buf;
754 for( i = bytes_to_copy; i < stored_bytes; i++ )
755 {
756 if( GET_BYTE( X, i ) != 0 )
757 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
758 }
759 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000760
Gilles Peskine220cc172018-11-20 16:47:47 +0100761 for( i = 0; i < bytes_to_copy; i++ )
762 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000763
764 return( 0 );
765}
766
767/*
768 * Left-shift: X <<= count
769 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200770int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000771{
Paul Bakker23986e52011-04-24 08:57:21 +0000772 int ret;
773 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200774 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000775
776 v0 = count / (biL );
777 t1 = count & (biL - 1);
778
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200779 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000780
Paul Bakkerf9688572011-05-05 10:00:45 +0000781 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200782 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000783
784 ret = 0;
785
786 /*
787 * shift by count / limb_size
788 */
789 if( v0 > 0 )
790 {
Paul Bakker23986e52011-04-24 08:57:21 +0000791 for( i = X->n; i > v0; i-- )
792 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000793
Paul Bakker23986e52011-04-24 08:57:21 +0000794 for( ; i > 0; i-- )
795 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000796 }
797
798 /*
799 * shift by count % limb_size
800 */
801 if( t1 > 0 )
802 {
803 for( i = v0; i < X->n; i++ )
804 {
805 r1 = X->p[i] >> (biL - t1);
806 X->p[i] <<= t1;
807 X->p[i] |= r0;
808 r0 = r1;
809 }
810 }
811
812cleanup:
813
814 return( ret );
815}
816
817/*
818 * Right-shift: X >>= count
819 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200820int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000821{
Paul Bakker23986e52011-04-24 08:57:21 +0000822 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200823 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000824
825 v0 = count / biL;
826 v1 = count & (biL - 1);
827
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100828 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200829 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100830
Paul Bakker5121ce52009-01-03 21:22:43 +0000831 /*
832 * shift by count / limb_size
833 */
834 if( v0 > 0 )
835 {
836 for( i = 0; i < X->n - v0; i++ )
837 X->p[i] = X->p[i + v0];
838
839 for( ; i < X->n; i++ )
840 X->p[i] = 0;
841 }
842
843 /*
844 * shift by count % limb_size
845 */
846 if( v1 > 0 )
847 {
Paul Bakker23986e52011-04-24 08:57:21 +0000848 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000849 {
Paul Bakker23986e52011-04-24 08:57:21 +0000850 r1 = X->p[i - 1] << (biL - v1);
851 X->p[i - 1] >>= v1;
852 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000853 r0 = r1;
854 }
855 }
856
857 return( 0 );
858}
859
860/*
861 * Compare unsigned values
862 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200863int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000864{
Paul Bakker23986e52011-04-24 08:57:21 +0000865 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000866
Paul Bakker23986e52011-04-24 08:57:21 +0000867 for( i = X->n; i > 0; i-- )
868 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000869 break;
870
Paul Bakker23986e52011-04-24 08:57:21 +0000871 for( j = Y->n; j > 0; j-- )
872 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000873 break;
874
Paul Bakker23986e52011-04-24 08:57:21 +0000875 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000876 return( 0 );
877
878 if( i > j ) return( 1 );
879 if( j > i ) return( -1 );
880
Paul Bakker23986e52011-04-24 08:57:21 +0000881 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000882 {
Paul Bakker23986e52011-04-24 08:57:21 +0000883 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
884 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000885 }
886
887 return( 0 );
888}
889
890/*
891 * Compare signed values
892 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200893int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000894{
Paul Bakker23986e52011-04-24 08:57:21 +0000895 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000896
Paul Bakker23986e52011-04-24 08:57:21 +0000897 for( i = X->n; i > 0; i-- )
898 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000899 break;
900
Paul Bakker23986e52011-04-24 08:57:21 +0000901 for( j = Y->n; j > 0; j-- )
902 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000903 break;
904
Paul Bakker23986e52011-04-24 08:57:21 +0000905 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000906 return( 0 );
907
908 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000909 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000910
911 if( X->s > 0 && Y->s < 0 ) return( 1 );
912 if( Y->s > 0 && X->s < 0 ) return( -1 );
913
Paul Bakker23986e52011-04-24 08:57:21 +0000914 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000915 {
Paul Bakker23986e52011-04-24 08:57:21 +0000916 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
917 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000918 }
919
920 return( 0 );
921}
922
Janos Follath3173a532019-10-14 09:09:32 +0100923/** Decide if an integer is less than the other, without branches.
924 *
925 * \param x First integer.
926 * \param y Second integer.
927 *
928 * \return 1 if \p x is less than \p y, 0 otherwise
929 */
Janos Follathc3b376e2019-10-11 14:21:53 +0100930static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
931 const mbedtls_mpi_uint y )
Janos Follathe0187b92019-09-05 14:47:19 +0100932{
933 mbedtls_mpi_uint ret;
934 mbedtls_mpi_uint cond;
935
936 /*
937 * Check if the most significant bits (MSB) of the operands are different.
938 */
939 cond = ( x ^ y );
940 /*
941 * If the MSB are the same then the difference x-y will be negative (and
942 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
943 */
944 ret = ( x - y ) & ~cond;
945 /*
946 * If the MSB are different, then the operand with the MSB of 1 is the
947 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
948 * the MSB of y is 0.)
949 */
950 ret |= y & cond;
951
952
Janos Follathdb9f4492019-10-14 08:59:14 +0100953 ret = ret >> ( biL - 1 );
Janos Follathe0187b92019-09-05 14:47:19 +0100954
Janos Follath58239612019-10-29 15:08:46 +0000955 return (unsigned) ret;
Janos Follathe0187b92019-09-05 14:47:19 +0100956}
957
958/*
959 * Compare signed values in constant time
960 */
Janos Follathc3b376e2019-10-11 14:21:53 +0100961int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
962 unsigned *ret )
Janos Follathe0187b92019-09-05 14:47:19 +0100963{
964 size_t i;
Janos Follatha2b9a962019-10-28 12:23:18 +0000965 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath8ec2a952019-10-28 12:31:34 +0000966 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathe0187b92019-09-05 14:47:19 +0100967
968 if( X->n != Y->n )
969 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
970
971 /*
Janos Follath51ed14e2019-10-28 12:12:15 +0000972 * Set sign_N to 1 if N >= 0, 0 if N < 0.
973 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathe0187b92019-09-05 14:47:19 +0100974 */
Janos Follath8ec2a952019-10-28 12:31:34 +0000975 X_is_negative = ( X->s & 2 ) >> 1;
976 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follathc3b376e2019-10-11 14:21:53 +0100977
978 /*
979 * If the signs are different, then the positive operand is the bigger.
Janos Follath8ec2a952019-10-28 12:31:34 +0000980 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
981 * is false if X is positive (X_is_negative == 0).
Janos Follathc3b376e2019-10-11 14:21:53 +0100982 */
Janos Follath8ec2a952019-10-28 12:31:34 +0000983 cond = ( X_is_negative ^ Y_is_negative );
984 *ret = cond & X_is_negative;
Janos Follathc3b376e2019-10-11 14:21:53 +0100985
986 /*
Janos Follatha2b9a962019-10-28 12:23:18 +0000987 * This is a constant-time function. We might have the result, but we still
Janos Follathc3b376e2019-10-11 14:21:53 +0100988 * need to go through the loop. Record if we have the result already.
989 */
Janos Follathe0187b92019-09-05 14:47:19 +0100990 done = cond;
991
992 for( i = X->n; i > 0; i-- )
993 {
994 /*
Janos Follathb4edac52019-11-05 12:24:52 +0000995 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
996 * X and Y are negative.
Janos Follathc3b376e2019-10-11 14:21:53 +0100997 *
998 * Again even if we can make a decision, we just mark the result and
999 * the fact that we are done and continue looping.
Janos Follathe0187b92019-09-05 14:47:19 +01001000 */
Janos Follathb4edac52019-11-05 12:24:52 +00001001 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1002 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathcff9e6e2019-10-28 12:37:21 +00001003 done |= cond;
Janos Follathe0187b92019-09-05 14:47:19 +01001004
1005 /*
Janos Follathb4edac52019-11-05 12:24:52 +00001006 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1007 * X and Y are positive.
Janos Follathc3b376e2019-10-11 14:21:53 +01001008 *
1009 * Again even if we can make a decision, we just mark the result and
1010 * the fact that we are done and continue looping.
Janos Follathe0187b92019-09-05 14:47:19 +01001011 */
Janos Follathb4edac52019-11-05 12:24:52 +00001012 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1013 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathcff9e6e2019-10-28 12:37:21 +00001014 done |= cond;
Janos Follathe0187b92019-09-05 14:47:19 +01001015 }
1016
1017 return( 0 );
1018}
1019
Paul Bakker5121ce52009-01-03 21:22:43 +00001020/*
1021 * Compare signed values
1022 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001023int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001024{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001025 mbedtls_mpi Y;
1026 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001027
1028 *p = ( z < 0 ) ? -z : z;
1029 Y.s = ( z < 0 ) ? -1 : 1;
1030 Y.n = 1;
1031 Y.p = p;
1032
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001033 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001034}
1035
1036/*
1037 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1038 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001039int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001040{
Paul Bakker23986e52011-04-24 08:57:21 +00001041 int ret;
1042 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001043 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +00001044
1045 if( X == B )
1046 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001047 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001048 }
1049
1050 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001051 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001052
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001053 /*
1054 * X should always be positive as a result of unsigned additions.
1055 */
1056 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001057
Paul Bakker23986e52011-04-24 08:57:21 +00001058 for( j = B->n; j > 0; j-- )
1059 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001060 break;
1061
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001062 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001063
1064 o = B->p; p = X->p; c = 0;
1065
Janos Follath6c922682015-10-30 17:43:11 +01001066 /*
1067 * tmp is used because it might happen that p == o
1068 */
Paul Bakker23986e52011-04-24 08:57:21 +00001069 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001070 {
Janos Follath6c922682015-10-30 17:43:11 +01001071 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001072 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001073 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001074 }
1075
1076 while( c != 0 )
1077 {
1078 if( i >= X->n )
1079 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001080 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001081 p = X->p + i;
1082 }
1083
Paul Bakker2d319fd2012-09-16 21:34:26 +00001084 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001085 }
1086
1087cleanup:
1088
1089 return( ret );
1090}
1091
1092/*
Gilles Peskined108d072020-06-04 15:00:49 +02001093 * Helper for mbedtls_mpi subtraction:
1094 * d -= s where d and s have the same size and d >= s.
Paul Bakker5121ce52009-01-03 21:22:43 +00001095 */
Gilles Peskined6496af2020-06-04 15:01:32 +02001096static void mpi_sub_hlp( size_t n,
1097 const mbedtls_mpi_uint *s,
1098 mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001099{
Paul Bakker23986e52011-04-24 08:57:21 +00001100 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001101 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001102
1103 for( i = c = 0; i < n; i++, s++, d++ )
1104 {
1105 z = ( *d < c ); *d -= c;
1106 c = ( *d < *s ) + z; *d -= *s;
1107 }
1108
1109 while( c != 0 )
1110 {
1111 z = ( *d < c ); *d -= c;
1112 c = z; i++; d++;
1113 }
1114}
1115
1116/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001117 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001118 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001119int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001120{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001121 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001122 int ret;
1123 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001125 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1126 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001127
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001128 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001129
1130 if( X == B )
1131 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001132 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001133 B = &TB;
1134 }
1135
1136 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001137 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001138
Paul Bakker1ef7a532009-06-20 10:50:55 +00001139 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001140 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001141 */
1142 X->s = 1;
1143
Paul Bakker5121ce52009-01-03 21:22:43 +00001144 ret = 0;
1145
Paul Bakker23986e52011-04-24 08:57:21 +00001146 for( n = B->n; n > 0; n-- )
1147 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001148 break;
1149
Paul Bakker23986e52011-04-24 08:57:21 +00001150 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001151
1152cleanup:
1153
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001154 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001155
1156 return( ret );
1157}
1158
1159/*
1160 * Signed addition: X = A + B
1161 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001162int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001163{
1164 int ret, s = A->s;
1165
1166 if( A->s * B->s < 0 )
1167 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001168 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001169 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001170 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001171 X->s = s;
1172 }
1173 else
1174 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001175 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001176 X->s = -s;
1177 }
1178 }
1179 else
1180 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001181 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001182 X->s = s;
1183 }
1184
1185cleanup:
1186
1187 return( ret );
1188}
1189
1190/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001191 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001192 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001193int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001194{
1195 int ret, s = A->s;
1196
1197 if( A->s * B->s > 0 )
1198 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001199 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001200 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001201 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001202 X->s = s;
1203 }
1204 else
1205 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001206 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001207 X->s = -s;
1208 }
1209 }
1210 else
1211 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001212 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001213 X->s = s;
1214 }
1215
1216cleanup:
1217
1218 return( ret );
1219}
1220
1221/*
1222 * Signed addition: X = A + b
1223 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001224int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001225{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001226 mbedtls_mpi _B;
1227 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001228
1229 p[0] = ( b < 0 ) ? -b : b;
1230 _B.s = ( b < 0 ) ? -1 : 1;
1231 _B.n = 1;
1232 _B.p = p;
1233
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001234 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001235}
1236
1237/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001238 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001239 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001240int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001241{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001242 mbedtls_mpi _B;
1243 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001244
1245 p[0] = ( b < 0 ) ? -b : b;
1246 _B.s = ( b < 0 ) ? -1 : 1;
1247 _B.n = 1;
1248 _B.p = p;
1249
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001250 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001251}
1252
1253/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001254 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001255 */
1256static
1257#if defined(__APPLE__) && defined(__arm__)
1258/*
1259 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1260 * appears to need this to prevent bad ARM code generation at -O3.
1261 */
1262__attribute__ ((noinline))
1263#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001264void 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 +00001265{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001266 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001267
1268#if defined(MULADDC_HUIT)
1269 for( ; i >= 8; i -= 8 )
1270 {
1271 MULADDC_INIT
1272 MULADDC_HUIT
1273 MULADDC_STOP
1274 }
1275
1276 for( ; i > 0; i-- )
1277 {
1278 MULADDC_INIT
1279 MULADDC_CORE
1280 MULADDC_STOP
1281 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001282#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001283 for( ; i >= 16; i -= 16 )
1284 {
1285 MULADDC_INIT
1286 MULADDC_CORE MULADDC_CORE
1287 MULADDC_CORE MULADDC_CORE
1288 MULADDC_CORE MULADDC_CORE
1289 MULADDC_CORE MULADDC_CORE
1290
1291 MULADDC_CORE MULADDC_CORE
1292 MULADDC_CORE MULADDC_CORE
1293 MULADDC_CORE MULADDC_CORE
1294 MULADDC_CORE MULADDC_CORE
1295 MULADDC_STOP
1296 }
1297
1298 for( ; i >= 8; i -= 8 )
1299 {
1300 MULADDC_INIT
1301 MULADDC_CORE MULADDC_CORE
1302 MULADDC_CORE MULADDC_CORE
1303
1304 MULADDC_CORE MULADDC_CORE
1305 MULADDC_CORE MULADDC_CORE
1306 MULADDC_STOP
1307 }
1308
1309 for( ; i > 0; i-- )
1310 {
1311 MULADDC_INIT
1312 MULADDC_CORE
1313 MULADDC_STOP
1314 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001315#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001316
1317 t++;
1318
1319 do {
1320 *d += c; c = ( *d < c ); d++;
1321 }
1322 while( c != 0 );
1323}
1324
1325/*
1326 * Baseline multiplication: X = A * B (HAC 14.12)
1327 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001328int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001329{
Paul Bakker23986e52011-04-24 08:57:21 +00001330 int ret;
1331 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001334 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1337 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001338
Paul Bakker23986e52011-04-24 08:57:21 +00001339 for( i = A->n; i > 0; i-- )
1340 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001341 break;
1342
Paul Bakker23986e52011-04-24 08:57:21 +00001343 for( j = B->n; j > 0; j-- )
1344 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001345 break;
1346
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001347 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1348 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001349
Paul Bakker23986e52011-04-24 08:57:21 +00001350 for( i++; j > 0; j-- )
1351 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001352
1353 X->s = A->s * B->s;
1354
1355cleanup:
1356
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001357 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001358
1359 return( ret );
1360}
1361
1362/*
1363 * Baseline multiplication: X = A * b
1364 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001366{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001367 mbedtls_mpi _B;
1368 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001369
1370 _B.s = 1;
1371 _B.n = 1;
1372 _B.p = p;
1373 p[0] = b;
1374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001375 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001376}
1377
1378/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001379 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1380 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001381 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001382static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1383 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001384{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001385#if defined(MBEDTLS_HAVE_UDBL)
1386 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001387#else
Simon Butcher9803d072016-01-03 00:24:34 +00001388 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1389 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001390 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1391 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001392 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001393#endif
1394
Simon Butcher15b15d12015-11-26 19:35:03 +00001395 /*
1396 * Check for overflow
1397 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001398 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001399 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001400 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001401
Simon Butcherf5ba0452015-12-27 23:01:55 +00001402 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001403 }
1404
1405#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001406 dividend = (mbedtls_t_udbl) u1 << biL;
1407 dividend |= (mbedtls_t_udbl) u0;
1408 quotient = dividend / d;
1409 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1410 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1411
1412 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001413 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001414
1415 return (mbedtls_mpi_uint) quotient;
1416#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001417
1418 /*
1419 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1420 * Vol. 2 - Seminumerical Algorithms, Knuth
1421 */
1422
1423 /*
1424 * Normalize the divisor, d, and dividend, u0, u1
1425 */
1426 s = mbedtls_clz( d );
1427 d = d << s;
1428
1429 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001430 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001431 u0 = u0 << s;
1432
1433 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001434 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001435
1436 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001437 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001438
1439 /*
1440 * Find the first quotient and remainder
1441 */
1442 q1 = u1 / d1;
1443 r0 = u1 - d1 * q1;
1444
1445 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1446 {
1447 q1 -= 1;
1448 r0 += d1;
1449
1450 if ( r0 >= radix ) break;
1451 }
1452
Simon Butcherf5ba0452015-12-27 23:01:55 +00001453 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001454 q0 = rAX / d1;
1455 r0 = rAX - q0 * d1;
1456
1457 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1458 {
1459 q0 -= 1;
1460 r0 += d1;
1461
1462 if ( r0 >= radix ) break;
1463 }
1464
1465 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001466 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001467
1468 quotient = q1 * radix + q0;
1469
1470 return quotient;
1471#endif
1472}
1473
1474/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001475 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001476 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001477int 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 +00001478{
Paul Bakker23986e52011-04-24 08:57:21 +00001479 int ret;
1480 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001481 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001483 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1484 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001485
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001486 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1487 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001489 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001490 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001491 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1492 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001493 return( 0 );
1494 }
1495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001496 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1497 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001498 X.s = Y.s = 1;
1499
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001500 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1501 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1502 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1503 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001504
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001505 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001506 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001507 {
1508 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001509 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1510 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001511 }
1512 else k = 0;
1513
1514 n = X.n - 1;
1515 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001516 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001517
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001518 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001519 {
1520 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001521 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001522 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001523 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001524
1525 for( i = n; i > t ; i-- )
1526 {
1527 if( X.p[i] >= Y.p[t] )
1528 Z.p[i - t - 1] = ~0;
1529 else
1530 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001531 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1532 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001533 }
1534
1535 Z.p[i - t - 1]++;
1536 do
1537 {
1538 Z.p[i - t - 1]--;
1539
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001540 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001541 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001542 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001543 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001544
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001545 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001546 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1547 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001548 T2.p[2] = X.p[i];
1549 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001550 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001552 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1553 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1554 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001555
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001556 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001557 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001558 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1559 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1560 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001561 Z.p[i - t - 1]--;
1562 }
1563 }
1564
1565 if( Q != NULL )
1566 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001567 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001568 Q->s = A->s * B->s;
1569 }
1570
1571 if( R != NULL )
1572 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001573 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001574 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001575 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001576
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001577 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001578 R->s = 1;
1579 }
1580
1581cleanup:
1582
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001583 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1584 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001585
1586 return( ret );
1587}
1588
1589/*
1590 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001591 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001592int 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 +00001593{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001594 mbedtls_mpi _B;
1595 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001596
1597 p[0] = ( b < 0 ) ? -b : b;
1598 _B.s = ( b < 0 ) ? -1 : 1;
1599 _B.n = 1;
1600 _B.p = p;
1601
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001602 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001603}
1604
1605/*
1606 * Modulo: R = A mod B
1607 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001608int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001609{
1610 int ret;
1611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001612 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1613 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001615 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001617 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1618 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001619
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001620 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1621 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001622
1623cleanup:
1624
1625 return( ret );
1626}
1627
1628/*
1629 * Modulo: r = A mod b
1630 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001631int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001632{
Paul Bakker23986e52011-04-24 08:57:21 +00001633 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001634 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001635
1636 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001637 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001638
1639 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001640 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001641
1642 /*
1643 * handle trivial cases
1644 */
1645 if( b == 1 )
1646 {
1647 *r = 0;
1648 return( 0 );
1649 }
1650
1651 if( b == 2 )
1652 {
1653 *r = A->p[0] & 1;
1654 return( 0 );
1655 }
1656
1657 /*
1658 * general case
1659 */
Paul Bakker23986e52011-04-24 08:57:21 +00001660 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001661 {
Paul Bakker23986e52011-04-24 08:57:21 +00001662 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001663 y = ( y << biH ) | ( x >> biH );
1664 z = y / b;
1665 y -= z * b;
1666
1667 x <<= biH;
1668 y = ( y << biH ) | ( x >> biH );
1669 z = y / b;
1670 y -= z * b;
1671 }
1672
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001673 /*
1674 * If A is negative, then the current y represents a negative value.
1675 * Flipping it to the positive side.
1676 */
1677 if( A->s < 0 && y != 0 )
1678 y = b - y;
1679
Paul Bakker5121ce52009-01-03 21:22:43 +00001680 *r = y;
1681
1682 return( 0 );
1683}
1684
1685/*
1686 * Fast Montgomery initialization (thanks to Tom St Denis)
1687 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001689{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001690 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001691 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001692
1693 x = m0;
1694 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001695
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001696 for( i = biL; i >= 8; i /= 2 )
1697 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001698
1699 *mm = ~x + 1;
1700}
1701
Gilles Peskined108d072020-06-04 15:00:49 +02001702/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1703 *
1704 * \param[in,out] A One of the numbers to multiply.
1705 * It must have at least one more limb than N
1706 * (A->n >= N->n + 1).
1707 * On successful completion, A contains the result of
1708 * the multiplication A * B * R^-1 mod N where
1709 * R = (2^ciL)^n.
1710 * \param[in] B One of the numbers to multiply.
1711 * It must be nonzero and must not have more limbs than N
1712 * (B->n <= N->n).
1713 * \param[in] N The modulo. N must be odd.
1714 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1715 * This is -N^-1 mod 2^ciL.
1716 * \param[in,out] T A bignum for temporary storage.
1717 * It must be at least twice the limb size of N plus 2
1718 * (T->n >= 2 * (N->n + 1)).
1719 * Its initial content is unused and
1720 * its final content is indeterminate.
1721 * Note that unlike the usual convention in the library
1722 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00001723 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001724static 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 +02001725 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001726{
Paul Bakker23986e52011-04-24 08:57:21 +00001727 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001728 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001729
1730 memset( T->p, 0, T->n * ciL );
1731
1732 d = T->p;
1733 n = N->n;
1734 m = ( B->n < n ) ? B->n : n;
1735
1736 for( i = 0; i < n; i++ )
1737 {
1738 /*
1739 * T = (T + u0*B + u1*N) / 2^biL
1740 */
1741 u0 = A->p[i];
1742 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1743
1744 mpi_mul_hlp( m, B->p, d, u0 );
1745 mpi_mul_hlp( n, N->p, d, u1 );
1746
1747 *d++ = u0; d[n + 1] = 0;
1748 }
1749
Paul Bakker66d5d072014-06-17 16:39:18 +02001750 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001751
Gilles Peskined108d072020-06-04 15:00:49 +02001752 /* If A >= N then A -= N. Do the subtraction unconditionally to prevent
1753 * timing attacks. Modify T as a side effect. */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001754 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001755 mpi_sub_hlp( n, N->p, A->p );
1756 else
1757 /* prevent timing attacks */
1758 mpi_sub_hlp( n, A->p, T->p );
1759}
1760
1761/*
1762 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskined108d072020-06-04 15:00:49 +02001763 *
1764 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001765 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001766static 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 +00001767{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001768 mbedtls_mpi_uint z = 1;
1769 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001770
Paul Bakker8ddb6452013-02-27 14:56:33 +01001771 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001772 U.p = &z;
1773
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001774 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001775}
1776
1777/*
1778 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1779 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001780int 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 +00001781{
Paul Bakker23986e52011-04-24 08:57:21 +00001782 int ret;
1783 size_t wbits, wsize, one = 1;
1784 size_t i, j, nblimbs;
1785 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001786 mbedtls_mpi_uint ei, mm, state;
1787 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001788 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001789
Hanno Becker930ec7d2018-03-09 10:48:00 +00001790 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001791 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001792
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001793 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1794 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001795
1796 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001797 * Init temps and window size
1798 */
1799 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001800 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1801 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001802 memset( W, 0, sizeof( W ) );
1803
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001804 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001805
1806 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1807 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1808
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001809#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001810 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1811 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001812#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001813
Paul Bakker5121ce52009-01-03 21:22:43 +00001814 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001815 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1816 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1817 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001818
1819 /*
Paul Bakker50546922012-05-19 08:40:49 +00001820 * Compensate for negative A (and correct at the end)
1821 */
1822 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001823 if( neg )
1824 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001825 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001826 Apos.s = 1;
1827 A = &Apos;
1828 }
1829
1830 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001831 * If 1st call, pre-compute R^2 mod N
1832 */
1833 if( _RR == NULL || _RR->p == NULL )
1834 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001835 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1836 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1837 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001838
1839 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001840 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001841 }
1842 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001843 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001844
1845 /*
1846 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1847 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001848 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1849 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001850 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001851 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001852
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001853 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001854
1855 /*
1856 * X = R^2 * R^-1 mod N = R mod N
1857 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001858 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001859 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001860
1861 if( wsize > 1 )
1862 {
1863 /*
1864 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1865 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001866 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001867
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001868 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1869 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001870
1871 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001872 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001873
Paul Bakker5121ce52009-01-03 21:22:43 +00001874 /*
1875 * W[i] = W[i - 1] * W[1]
1876 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001877 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001878 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1880 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001881
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001882 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001883 }
1884 }
1885
1886 nblimbs = E->n;
1887 bufsize = 0;
1888 nbits = 0;
1889 wbits = 0;
1890 state = 0;
1891
1892 while( 1 )
1893 {
1894 if( bufsize == 0 )
1895 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001896 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001897 break;
1898
Paul Bakker0d7702c2013-10-29 16:18:35 +01001899 nblimbs--;
1900
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001901 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001902 }
1903
1904 bufsize--;
1905
1906 ei = (E->p[nblimbs] >> bufsize) & 1;
1907
1908 /*
1909 * skip leading 0s
1910 */
1911 if( ei == 0 && state == 0 )
1912 continue;
1913
1914 if( ei == 0 && state == 1 )
1915 {
1916 /*
1917 * out of window, square X
1918 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001919 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001920 continue;
1921 }
1922
1923 /*
1924 * add ei to current window
1925 */
1926 state = 2;
1927
1928 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001929 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001930
1931 if( nbits == wsize )
1932 {
1933 /*
1934 * X = X^wsize R^-1 mod N
1935 */
1936 for( i = 0; i < wsize; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001937 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001938
1939 /*
1940 * X = X * W[wbits] R^-1 mod N
1941 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001942 mpi_montmul( X, &W[wbits], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001943
1944 state--;
1945 nbits = 0;
1946 wbits = 0;
1947 }
1948 }
1949
1950 /*
1951 * process the remaining bits
1952 */
1953 for( i = 0; i < nbits; i++ )
1954 {
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001955 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956
1957 wbits <<= 1;
1958
Paul Bakker66d5d072014-06-17 16:39:18 +02001959 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001960 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001961 }
1962
1963 /*
1964 * X = A^E * R * R^-1 mod N = A^E mod N
1965 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001966 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001967
Hanno Beckera4af1c42017-04-18 09:07:45 +01001968 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001969 {
1970 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001971 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001972 }
1973
Paul Bakker5121ce52009-01-03 21:22:43 +00001974cleanup:
1975
Paul Bakker66d5d072014-06-17 16:39:18 +02001976 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001977 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001978
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001979 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001980
Paul Bakker75a28602014-03-31 12:08:17 +02001981 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001982 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001983
1984 return( ret );
1985}
1986
Paul Bakker5121ce52009-01-03 21:22:43 +00001987/*
1988 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1989 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001990int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001991{
Paul Bakker23986e52011-04-24 08:57:21 +00001992 int ret;
1993 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001994 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001995
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001996 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001997
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001998 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1999 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002000
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002001 lz = mbedtls_mpi_lsb( &TA );
2002 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002003
Paul Bakker66d5d072014-06-17 16:39:18 +02002004 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002005 lz = lzt;
2006
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002007 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2008 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002009
Paul Bakker5121ce52009-01-03 21:22:43 +00002010 TA.s = TB.s = 1;
2011
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002012 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002013 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002014 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2015 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002016
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002017 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002018 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002019 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2020 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002021 }
2022 else
2023 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002024 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2025 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002026 }
2027 }
2028
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2030 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002031
2032cleanup:
2033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002035
2036 return( ret );
2037}
2038
Paul Bakker33dc46b2014-04-30 16:11:39 +02002039/*
2040 * Fill X with size bytes of random.
2041 *
2042 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002043 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002044 * deterministic, eg for tests).
2045 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002047 int (*f_rng)(void *, unsigned char *, size_t),
2048 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002049{
Paul Bakker23986e52011-04-24 08:57:21 +00002050 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002051 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02002052
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002053 if( size > MBEDTLS_MPI_MAX_SIZE )
2054 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002055
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002056 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2057 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002058
2059cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01002060 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002061 return( ret );
2062}
2063
Paul Bakker5121ce52009-01-03 21:22:43 +00002064/*
2065 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2066 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002067int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002068{
2069 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002070 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002071
Hanno Becker4bcb4912017-04-18 15:49:39 +01002072 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002073 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002074
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002075 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2076 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2077 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002078
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002079 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002080
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002081 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002082 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002083 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002084 goto cleanup;
2085 }
2086
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002087 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2088 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2089 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2090 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002091
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002092 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2093 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2094 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2095 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002096
2097 do
2098 {
2099 while( ( TU.p[0] & 1 ) == 0 )
2100 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002101 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002102
2103 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2104 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002105 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2106 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002107 }
2108
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002109 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2110 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002111 }
2112
2113 while( ( TV.p[0] & 1 ) == 0 )
2114 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002115 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002116
2117 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2118 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002119 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2120 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002121 }
2122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002123 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2124 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002125 }
2126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002127 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002128 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002129 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2130 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2131 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002132 }
2133 else
2134 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002135 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2136 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2137 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002138 }
2139 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002140 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002141
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002142 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2143 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2146 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002147
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002148 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002149
2150cleanup:
2151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002152 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2153 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2154 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002155
2156 return( ret );
2157}
2158
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002159#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002160
Paul Bakker5121ce52009-01-03 21:22:43 +00002161static const int small_prime[] =
2162{
2163 3, 5, 7, 11, 13, 17, 19, 23,
2164 29, 31, 37, 41, 43, 47, 53, 59,
2165 61, 67, 71, 73, 79, 83, 89, 97,
2166 101, 103, 107, 109, 113, 127, 131, 137,
2167 139, 149, 151, 157, 163, 167, 173, 179,
2168 181, 191, 193, 197, 199, 211, 223, 227,
2169 229, 233, 239, 241, 251, 257, 263, 269,
2170 271, 277, 281, 283, 293, 307, 311, 313,
2171 317, 331, 337, 347, 349, 353, 359, 367,
2172 373, 379, 383, 389, 397, 401, 409, 419,
2173 421, 431, 433, 439, 443, 449, 457, 461,
2174 463, 467, 479, 487, 491, 499, 503, 509,
2175 521, 523, 541, 547, 557, 563, 569, 571,
2176 577, 587, 593, 599, 601, 607, 613, 617,
2177 619, 631, 641, 643, 647, 653, 659, 661,
2178 673, 677, 683, 691, 701, 709, 719, 727,
2179 733, 739, 743, 751, 757, 761, 769, 773,
2180 787, 797, 809, 811, 821, 823, 827, 829,
2181 839, 853, 857, 859, 863, 877, 881, 883,
2182 887, 907, 911, 919, 929, 937, 941, 947,
2183 953, 967, 971, 977, 983, 991, 997, -103
2184};
2185
2186/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002187 * Small divisors test (X must be positive)
2188 *
2189 * Return values:
2190 * 0: no small factor (possible prime, more tests needed)
2191 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002192 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002193 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002194 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002195static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002196{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002197 int ret = 0;
2198 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002199 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002200
Paul Bakker5121ce52009-01-03 21:22:43 +00002201 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002202 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002203
2204 for( i = 0; small_prime[i] > 0; i++ )
2205 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002207 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002209 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002210
2211 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002212 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002213 }
2214
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002215cleanup:
2216 return( ret );
2217}
2218
2219/*
2220 * Miller-Rabin pseudo-primality test (HAC 4.24)
2221 */
Janos Follath72d555d2018-09-03 14:45:23 +01002222static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002223 int (*f_rng)(void *, unsigned char *, size_t),
2224 void *p_rng )
2225{
Pascal Junodb99183d2015-03-11 16:49:45 +01002226 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002227 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002228 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002229
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002230 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2231 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002232
Paul Bakker5121ce52009-01-03 21:22:43 +00002233 /*
2234 * W = |X| - 1
2235 * R = W >> lsb( W )
2236 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002237 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2238 s = mbedtls_mpi_lsb( &W );
2239 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2240 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002241
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002242 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002243
Janos Follath72d555d2018-09-03 14:45:23 +01002244 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002245 {
2246 /*
2247 * pick a random A, 1 < A < |X| - 1
2248 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002249 count = 0;
2250 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002251 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002252
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002253 j = mbedtls_mpi_bitlen( &A );
2254 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002255 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002256 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002257 }
2258
2259 if (count++ > 30) {
Jens Wiklanderb2aa9382019-01-17 13:30:57 +01002260 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2261 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002262 }
2263
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002264 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2265 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002266
2267 /*
2268 * A = A^R mod |X|
2269 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002270 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002271
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2273 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002274 continue;
2275
2276 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002277 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002278 {
2279 /*
2280 * A = A * A mod |X|
2281 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002282 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2283 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002284
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002285 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002286 break;
2287
2288 j++;
2289 }
2290
2291 /*
2292 * not prime if A != |X| - 1 or A == 1
2293 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002294 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2295 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002296 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002297 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002298 break;
2299 }
2300 }
2301
2302cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002303 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2304 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002305
2306 return( ret );
2307}
2308
2309/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002310 * Pseudo-primality test: small factors, then Miller-Rabin
2311 */
Darryl Green94759f62018-10-16 15:09:19 +01002312static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002313 int (*f_rng)(void *, unsigned char *, size_t),
2314 void *p_rng )
2315{
2316 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002317 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002318
2319 XX.s = 1;
2320 XX.n = X->n;
2321 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002322
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002323 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2324 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2325 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002327 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002328 return( 0 );
2329
2330 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2331 {
2332 if( ret == 1 )
2333 return( 0 );
2334
2335 return( ret );
2336 }
2337
Janos Follath72d555d2018-09-03 14:45:23 +01002338 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2339}
2340
2341/*
2342 * Pseudo-primality test, error probability 2^-80
2343 */
2344int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2345 int (*f_rng)(void *, unsigned char *, size_t),
2346 void *p_rng )
2347{
2348 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002349}
2350
2351/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002352 * Prime number generation
2353 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002354int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002355 int (*f_rng)(void *, unsigned char *, size_t),
2356 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002357{
Paul Bakker23986e52011-04-24 08:57:21 +00002358 int ret;
2359 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002360 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002361 mbedtls_mpi_uint r;
2362 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002363
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002364 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2365 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002366
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002368
2369 n = BITS_TO_LIMBS( nbits );
2370
Janos Follath72d555d2018-09-03 14:45:23 +01002371 /*
2372 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2373 */
2374 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2375 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2376 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002378 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002379
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002380 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002381 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002382
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002383 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002384
2385 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002386
2387 if( dh_flag == 0 )
2388 {
Janos Follath72d555d2018-09-03 14:45:23 +01002389 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002390 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002391 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002392 goto cleanup;
2393
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002394 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002395 }
2396 }
2397 else
2398 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002399 /*
2400 * An necessary condition for Y and X = 2Y + 1 to be prime
2401 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2402 * Make sure it is satisfied, while keeping X = 3 mod 4
2403 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002404
2405 X->p[0] |= 2;
2406
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002407 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002408 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002409 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002410 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002411 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002412
2413 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002414 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2415 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002416
2417 while( 1 )
2418 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002419 /*
2420 * First, check small factors for X and Y
2421 * before doing Miller-Rabin on any of them
2422 */
2423 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2424 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002425 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2426 == 0 &&
2427 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2428 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002429 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002430 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002431 }
2432
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002433 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002434 goto cleanup;
2435
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002436 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002437 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002438 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2439 * so up Y by 6 and X by 12.
2440 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002441 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2442 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002443 }
2444 }
2445
2446cleanup:
2447
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002448 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002449
2450 return( ret );
2451}
2452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002453#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002455#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002456
Paul Bakker23986e52011-04-24 08:57:21 +00002457#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002458
2459static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2460{
2461 { 693, 609, 21 },
2462 { 1764, 868, 28 },
2463 { 768454923, 542167814, 1 }
2464};
2465
Paul Bakker5121ce52009-01-03 21:22:43 +00002466/*
2467 * Checkup routine
2468 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002469int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002470{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002471 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002472 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002473
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002474 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2475 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002476
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002477 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002478 "EFE021C2645FD1DC586E69184AF4A31E" \
2479 "D5F53E93B5F123FA41680867BA110131" \
2480 "944FE7952E2517337780CB0DB80E61AA" \
2481 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002483 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002484 "B2E7EFD37075B9F03FF989C7C5051C20" \
2485 "34D2A323810251127E7BF8625A4F49A5" \
2486 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2487 "5B5C25763222FEFCCFC38B832366C29E" ) );
2488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002489 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002490 "0066A198186C18C10B2F5ED9B522752A" \
2491 "9830B69916E535C8F047518A889A43A5" \
2492 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2493
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002494 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002496 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002497 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2498 "9E857EA95A03512E2BAE7391688D264A" \
2499 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2500 "8001B72E848A38CAE1C65F78E56ABDEF" \
2501 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2502 "ECF677152EF804370C1A305CAF3B5BF1" \
2503 "30879B56C61DE584A0F53A2447A51E" ) );
2504
2505 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002506 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002508 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002509 {
2510 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002511 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002512
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002513 ret = 1;
2514 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002515 }
2516
2517 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002518 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002519
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002520 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002522 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002523 "256567336059E52CAE22925474705F39A94" ) );
2524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002525 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002526 "6613F26162223DF488E9CD48CC132C7A" \
2527 "0AC93C701B001B092E4E5B9F73BCD27B" \
2528 "9EE50D0657C77F374E903CDFA4C642" ) );
2529
2530 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002531 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002532
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002533 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2534 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002535 {
2536 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002537 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002538
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002539 ret = 1;
2540 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002541 }
2542
2543 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002544 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002545
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002546 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002547
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002548 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002549 "36E139AEA55215609D2816998ED020BB" \
2550 "BD96C37890F65171D948E9BC7CBAA4D9" \
2551 "325D24D6A3C12710F10A09FA08AB87" ) );
2552
2553 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002554 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002555
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002556 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002557 {
2558 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002559 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002560
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002561 ret = 1;
2562 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002563 }
2564
2565 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002566 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002567
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002568 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002569
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002570 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002571 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2572 "C3DBA76456363A10869622EAC2DD84EC" \
2573 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2574
2575 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002576 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002578 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002579 {
2580 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002581 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002582
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002583 ret = 1;
2584 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002585 }
2586
2587 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002588 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002589
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002590 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002591 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002592
Paul Bakker66d5d072014-06-17 16:39:18 +02002593 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002594 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002595 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2596 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002597
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002598 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002599
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002600 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002601 {
2602 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002603 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002604
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002605 ret = 1;
2606 goto cleanup;
2607 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002608 }
2609
2610 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002611 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002612
Paul Bakker5121ce52009-01-03 21:22:43 +00002613cleanup:
2614
2615 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002616 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002617
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002618 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2619 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002620
2621 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002622 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002623
2624 return( ret );
2625}
2626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002627#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002628
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002629#endif /* MBEDTLS_BIGNUM_C */