blob: d139ecede549dbd3a8cab11e06c7558d2c028a08 [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/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001093 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001094 */
Gilles Peskined6496af2020-06-04 15:01:32 +02001095static void mpi_sub_hlp( size_t n,
1096 const mbedtls_mpi_uint *s,
1097 mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001098{
Paul Bakker23986e52011-04-24 08:57:21 +00001099 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001100 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001101
1102 for( i = c = 0; i < n; i++, s++, d++ )
1103 {
1104 z = ( *d < c ); *d -= c;
1105 c = ( *d < *s ) + z; *d -= *s;
1106 }
1107
1108 while( c != 0 )
1109 {
1110 z = ( *d < c ); *d -= c;
1111 c = z; i++; d++;
1112 }
1113}
1114
1115/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001116 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001117 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001118int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001119{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001120 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001121 int ret;
1122 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001123
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001124 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1125 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001127 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001128
1129 if( X == B )
1130 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001131 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001132 B = &TB;
1133 }
1134
1135 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001136 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001137
Paul Bakker1ef7a532009-06-20 10:50:55 +00001138 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001139 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001140 */
1141 X->s = 1;
1142
Paul Bakker5121ce52009-01-03 21:22:43 +00001143 ret = 0;
1144
Paul Bakker23986e52011-04-24 08:57:21 +00001145 for( n = B->n; n > 0; n-- )
1146 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001147 break;
1148
Paul Bakker23986e52011-04-24 08:57:21 +00001149 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001150
1151cleanup:
1152
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001153 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001154
1155 return( ret );
1156}
1157
1158/*
1159 * Signed addition: X = A + B
1160 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001161int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001162{
1163 int ret, s = A->s;
1164
1165 if( A->s * B->s < 0 )
1166 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001167 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001168 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001169 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001170 X->s = s;
1171 }
1172 else
1173 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001174 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001175 X->s = -s;
1176 }
1177 }
1178 else
1179 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001180 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001181 X->s = s;
1182 }
1183
1184cleanup:
1185
1186 return( ret );
1187}
1188
1189/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001190 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001191 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001192int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001193{
1194 int ret, s = A->s;
1195
1196 if( A->s * B->s > 0 )
1197 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001198 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001199 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001200 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001201 X->s = s;
1202 }
1203 else
1204 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001205 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001206 X->s = -s;
1207 }
1208 }
1209 else
1210 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001211 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001212 X->s = s;
1213 }
1214
1215cleanup:
1216
1217 return( ret );
1218}
1219
1220/*
1221 * Signed addition: X = A + b
1222 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001223int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001224{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001225 mbedtls_mpi _B;
1226 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001227
1228 p[0] = ( b < 0 ) ? -b : b;
1229 _B.s = ( b < 0 ) ? -1 : 1;
1230 _B.n = 1;
1231 _B.p = p;
1232
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001233 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001234}
1235
1236/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001237 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001238 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001239int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001240{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001241 mbedtls_mpi _B;
1242 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001243
1244 p[0] = ( b < 0 ) ? -b : b;
1245 _B.s = ( b < 0 ) ? -1 : 1;
1246 _B.n = 1;
1247 _B.p = p;
1248
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001249 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001250}
1251
1252/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001253 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001254 */
1255static
1256#if defined(__APPLE__) && defined(__arm__)
1257/*
1258 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1259 * appears to need this to prevent bad ARM code generation at -O3.
1260 */
1261__attribute__ ((noinline))
1262#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001263void 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 +00001264{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001265 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001266
1267#if defined(MULADDC_HUIT)
1268 for( ; i >= 8; i -= 8 )
1269 {
1270 MULADDC_INIT
1271 MULADDC_HUIT
1272 MULADDC_STOP
1273 }
1274
1275 for( ; i > 0; i-- )
1276 {
1277 MULADDC_INIT
1278 MULADDC_CORE
1279 MULADDC_STOP
1280 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001281#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001282 for( ; i >= 16; i -= 16 )
1283 {
1284 MULADDC_INIT
1285 MULADDC_CORE MULADDC_CORE
1286 MULADDC_CORE MULADDC_CORE
1287 MULADDC_CORE MULADDC_CORE
1288 MULADDC_CORE MULADDC_CORE
1289
1290 MULADDC_CORE MULADDC_CORE
1291 MULADDC_CORE MULADDC_CORE
1292 MULADDC_CORE MULADDC_CORE
1293 MULADDC_CORE MULADDC_CORE
1294 MULADDC_STOP
1295 }
1296
1297 for( ; i >= 8; i -= 8 )
1298 {
1299 MULADDC_INIT
1300 MULADDC_CORE MULADDC_CORE
1301 MULADDC_CORE MULADDC_CORE
1302
1303 MULADDC_CORE MULADDC_CORE
1304 MULADDC_CORE MULADDC_CORE
1305 MULADDC_STOP
1306 }
1307
1308 for( ; i > 0; i-- )
1309 {
1310 MULADDC_INIT
1311 MULADDC_CORE
1312 MULADDC_STOP
1313 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001314#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001315
1316 t++;
1317
1318 do {
1319 *d += c; c = ( *d < c ); d++;
1320 }
1321 while( c != 0 );
1322}
1323
1324/*
1325 * Baseline multiplication: X = A * B (HAC 14.12)
1326 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001327int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001328{
Paul Bakker23986e52011-04-24 08:57:21 +00001329 int ret;
1330 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001331 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001333 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001335 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1336 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001337
Paul Bakker23986e52011-04-24 08:57:21 +00001338 for( i = A->n; i > 0; i-- )
1339 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001340 break;
1341
Paul Bakker23986e52011-04-24 08:57:21 +00001342 for( j = B->n; j > 0; j-- )
1343 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001344 break;
1345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001346 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1347 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001348
Paul Bakker23986e52011-04-24 08:57:21 +00001349 for( i++; j > 0; j-- )
1350 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001351
1352 X->s = A->s * B->s;
1353
1354cleanup:
1355
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001356 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001357
1358 return( ret );
1359}
1360
1361/*
1362 * Baseline multiplication: X = A * b
1363 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001364int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001365{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366 mbedtls_mpi _B;
1367 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001368
1369 _B.s = 1;
1370 _B.n = 1;
1371 _B.p = p;
1372 p[0] = b;
1373
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001374 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001375}
1376
1377/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001378 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1379 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001380 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001381static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1382 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001383{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001384#if defined(MBEDTLS_HAVE_UDBL)
1385 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001386#else
Simon Butcher9803d072016-01-03 00:24:34 +00001387 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1388 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001389 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1390 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001391 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001392#endif
1393
Simon Butcher15b15d12015-11-26 19:35:03 +00001394 /*
1395 * Check for overflow
1396 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001397 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001398 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001399 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001400
Simon Butcherf5ba0452015-12-27 23:01:55 +00001401 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001402 }
1403
1404#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001405 dividend = (mbedtls_t_udbl) u1 << biL;
1406 dividend |= (mbedtls_t_udbl) u0;
1407 quotient = dividend / d;
1408 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1409 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1410
1411 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001412 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001413
1414 return (mbedtls_mpi_uint) quotient;
1415#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001416
1417 /*
1418 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1419 * Vol. 2 - Seminumerical Algorithms, Knuth
1420 */
1421
1422 /*
1423 * Normalize the divisor, d, and dividend, u0, u1
1424 */
1425 s = mbedtls_clz( d );
1426 d = d << s;
1427
1428 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001429 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001430 u0 = u0 << s;
1431
1432 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001433 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001434
1435 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001436 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001437
1438 /*
1439 * Find the first quotient and remainder
1440 */
1441 q1 = u1 / d1;
1442 r0 = u1 - d1 * q1;
1443
1444 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1445 {
1446 q1 -= 1;
1447 r0 += d1;
1448
1449 if ( r0 >= radix ) break;
1450 }
1451
Simon Butcherf5ba0452015-12-27 23:01:55 +00001452 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001453 q0 = rAX / d1;
1454 r0 = rAX - q0 * d1;
1455
1456 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1457 {
1458 q0 -= 1;
1459 r0 += d1;
1460
1461 if ( r0 >= radix ) break;
1462 }
1463
1464 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001465 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001466
1467 quotient = q1 * radix + q0;
1468
1469 return quotient;
1470#endif
1471}
1472
1473/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001474 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001475 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001476int 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 +00001477{
Paul Bakker23986e52011-04-24 08:57:21 +00001478 int ret;
1479 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001480 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001482 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1483 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001484
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001485 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1486 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001487
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001488 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001489 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001490 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1491 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001492 return( 0 );
1493 }
1494
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001495 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1496 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001497 X.s = Y.s = 1;
1498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001499 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1500 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1501 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1502 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001503
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001504 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001505 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001506 {
1507 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001508 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1509 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001510 }
1511 else k = 0;
1512
1513 n = X.n - 1;
1514 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001515 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001516
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001517 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001518 {
1519 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001520 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001521 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001522 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001523
1524 for( i = n; i > t ; i-- )
1525 {
1526 if( X.p[i] >= Y.p[t] )
1527 Z.p[i - t - 1] = ~0;
1528 else
1529 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001530 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1531 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001532 }
1533
1534 Z.p[i - t - 1]++;
1535 do
1536 {
1537 Z.p[i - t - 1]--;
1538
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001540 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001541 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001542 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001543
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001544 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001545 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1546 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001547 T2.p[2] = X.p[i];
1548 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001549 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001550
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001551 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1552 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1553 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001555 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001556 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001557 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1558 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1559 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001560 Z.p[i - t - 1]--;
1561 }
1562 }
1563
1564 if( Q != NULL )
1565 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001566 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001567 Q->s = A->s * B->s;
1568 }
1569
1570 if( R != NULL )
1571 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001572 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001573 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001574 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001576 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001577 R->s = 1;
1578 }
1579
1580cleanup:
1581
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001582 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1583 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001584
1585 return( ret );
1586}
1587
1588/*
1589 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001590 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001591int 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 +00001592{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001593 mbedtls_mpi _B;
1594 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001595
1596 p[0] = ( b < 0 ) ? -b : b;
1597 _B.s = ( b < 0 ) ? -1 : 1;
1598 _B.n = 1;
1599 _B.p = p;
1600
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001601 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001602}
1603
1604/*
1605 * Modulo: R = A mod B
1606 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001607int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001608{
1609 int ret;
1610
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001611 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1612 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001613
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001614 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001615
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001616 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1617 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001619 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1620 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001621
1622cleanup:
1623
1624 return( ret );
1625}
1626
1627/*
1628 * Modulo: r = A mod b
1629 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001630int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001631{
Paul Bakker23986e52011-04-24 08:57:21 +00001632 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001633 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001634
1635 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001637
1638 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001639 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001640
1641 /*
1642 * handle trivial cases
1643 */
1644 if( b == 1 )
1645 {
1646 *r = 0;
1647 return( 0 );
1648 }
1649
1650 if( b == 2 )
1651 {
1652 *r = A->p[0] & 1;
1653 return( 0 );
1654 }
1655
1656 /*
1657 * general case
1658 */
Paul Bakker23986e52011-04-24 08:57:21 +00001659 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001660 {
Paul Bakker23986e52011-04-24 08:57:21 +00001661 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001662 y = ( y << biH ) | ( x >> biH );
1663 z = y / b;
1664 y -= z * b;
1665
1666 x <<= biH;
1667 y = ( y << biH ) | ( x >> biH );
1668 z = y / b;
1669 y -= z * b;
1670 }
1671
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001672 /*
1673 * If A is negative, then the current y represents a negative value.
1674 * Flipping it to the positive side.
1675 */
1676 if( A->s < 0 && y != 0 )
1677 y = b - y;
1678
Paul Bakker5121ce52009-01-03 21:22:43 +00001679 *r = y;
1680
1681 return( 0 );
1682}
1683
1684/*
1685 * Fast Montgomery initialization (thanks to Tom St Denis)
1686 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001687static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001688{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001689 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001690 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001691
1692 x = m0;
1693 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001694
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001695 for( i = biL; i >= 8; i /= 2 )
1696 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001697
1698 *mm = ~x + 1;
1699}
1700
1701/*
1702 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1703 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001704static 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 +02001705 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001706{
Paul Bakker23986e52011-04-24 08:57:21 +00001707 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001708 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001709
1710 memset( T->p, 0, T->n * ciL );
1711
1712 d = T->p;
1713 n = N->n;
1714 m = ( B->n < n ) ? B->n : n;
1715
1716 for( i = 0; i < n; i++ )
1717 {
1718 /*
1719 * T = (T + u0*B + u1*N) / 2^biL
1720 */
1721 u0 = A->p[i];
1722 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1723
1724 mpi_mul_hlp( m, B->p, d, u0 );
1725 mpi_mul_hlp( n, N->p, d, u1 );
1726
1727 *d++ = u0; d[n + 1] = 0;
1728 }
1729
Paul Bakker66d5d072014-06-17 16:39:18 +02001730 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001731
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001732 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001733 mpi_sub_hlp( n, N->p, A->p );
1734 else
1735 /* prevent timing attacks */
1736 mpi_sub_hlp( n, A->p, T->p );
1737}
1738
1739/*
1740 * Montgomery reduction: A = A * R^-1 mod N
1741 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001742static 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 +00001743{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001744 mbedtls_mpi_uint z = 1;
1745 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001746
Paul Bakker8ddb6452013-02-27 14:56:33 +01001747 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001748 U.p = &z;
1749
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001750 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001751}
1752
1753/*
1754 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1755 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001756int 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 +00001757{
Paul Bakker23986e52011-04-24 08:57:21 +00001758 int ret;
1759 size_t wbits, wsize, one = 1;
1760 size_t i, j, nblimbs;
1761 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001762 mbedtls_mpi_uint ei, mm, state;
1763 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001764 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001765
Hanno Becker930ec7d2018-03-09 10:48:00 +00001766 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001767 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001768
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001769 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1770 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001771
1772 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001773 * Init temps and window size
1774 */
1775 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001776 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1777 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001778 memset( W, 0, sizeof( W ) );
1779
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001780 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001781
1782 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1783 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1784
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001785#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001786 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1787 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001788#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001789
Paul Bakker5121ce52009-01-03 21:22:43 +00001790 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001791 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1792 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1793 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001794
1795 /*
Paul Bakker50546922012-05-19 08:40:49 +00001796 * Compensate for negative A (and correct at the end)
1797 */
1798 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001799 if( neg )
1800 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001801 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001802 Apos.s = 1;
1803 A = &Apos;
1804 }
1805
1806 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001807 * If 1st call, pre-compute R^2 mod N
1808 */
1809 if( _RR == NULL || _RR->p == NULL )
1810 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001811 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1812 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1813 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001814
1815 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001817 }
1818 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001819 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001820
1821 /*
1822 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1823 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1825 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001826 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001827 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001828
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001829 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001830
1831 /*
1832 * X = R^2 * R^-1 mod N = R mod N
1833 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001834 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001835 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001836
1837 if( wsize > 1 )
1838 {
1839 /*
1840 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1841 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001842 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001843
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1845 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846
1847 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001848 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001849
Paul Bakker5121ce52009-01-03 21:22:43 +00001850 /*
1851 * W[i] = W[i - 1] * W[1]
1852 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001853 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001854 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001855 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1856 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001857
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001858 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001859 }
1860 }
1861
1862 nblimbs = E->n;
1863 bufsize = 0;
1864 nbits = 0;
1865 wbits = 0;
1866 state = 0;
1867
1868 while( 1 )
1869 {
1870 if( bufsize == 0 )
1871 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001872 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001873 break;
1874
Paul Bakker0d7702c2013-10-29 16:18:35 +01001875 nblimbs--;
1876
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001877 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001878 }
1879
1880 bufsize--;
1881
1882 ei = (E->p[nblimbs] >> bufsize) & 1;
1883
1884 /*
1885 * skip leading 0s
1886 */
1887 if( ei == 0 && state == 0 )
1888 continue;
1889
1890 if( ei == 0 && state == 1 )
1891 {
1892 /*
1893 * out of window, square X
1894 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001895 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001896 continue;
1897 }
1898
1899 /*
1900 * add ei to current window
1901 */
1902 state = 2;
1903
1904 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001905 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001906
1907 if( nbits == wsize )
1908 {
1909 /*
1910 * X = X^wsize R^-1 mod N
1911 */
1912 for( i = 0; i < wsize; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001913 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001914
1915 /*
1916 * X = X * W[wbits] R^-1 mod N
1917 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001918 mpi_montmul( X, &W[wbits], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001919
1920 state--;
1921 nbits = 0;
1922 wbits = 0;
1923 }
1924 }
1925
1926 /*
1927 * process the remaining bits
1928 */
1929 for( i = 0; i < nbits; i++ )
1930 {
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001931 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001932
1933 wbits <<= 1;
1934
Paul Bakker66d5d072014-06-17 16:39:18 +02001935 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001936 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001937 }
1938
1939 /*
1940 * X = A^E * R * R^-1 mod N = A^E mod N
1941 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001942 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001943
Hanno Beckera4af1c42017-04-18 09:07:45 +01001944 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001945 {
1946 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001947 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001948 }
1949
Paul Bakker5121ce52009-01-03 21:22:43 +00001950cleanup:
1951
Paul Bakker66d5d072014-06-17 16:39:18 +02001952 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001953 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001954
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001955 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001956
Paul Bakker75a28602014-03-31 12:08:17 +02001957 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001958 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001959
1960 return( ret );
1961}
1962
Paul Bakker5121ce52009-01-03 21:22:43 +00001963/*
1964 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1965 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001966int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001967{
Paul Bakker23986e52011-04-24 08:57:21 +00001968 int ret;
1969 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001970 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001971
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001972 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001973
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001974 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1975 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001976
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001977 lz = mbedtls_mpi_lsb( &TA );
1978 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001979
Paul Bakker66d5d072014-06-17 16:39:18 +02001980 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001981 lz = lzt;
1982
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001983 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1984 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001985
Paul Bakker5121ce52009-01-03 21:22:43 +00001986 TA.s = TB.s = 1;
1987
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001989 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001990 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1991 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001992
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001993 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001994 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001995 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1996 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001997 }
1998 else
1999 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002000 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2001 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002002 }
2003 }
2004
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002005 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2006 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002007
2008cleanup:
2009
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002010 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002011
2012 return( ret );
2013}
2014
Paul Bakker33dc46b2014-04-30 16:11:39 +02002015/*
2016 * Fill X with size bytes of random.
2017 *
2018 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002019 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002020 * deterministic, eg for tests).
2021 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002022int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002023 int (*f_rng)(void *, unsigned char *, size_t),
2024 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002025{
Paul Bakker23986e52011-04-24 08:57:21 +00002026 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002027 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02002028
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029 if( size > MBEDTLS_MPI_MAX_SIZE )
2030 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002032 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2033 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002034
2035cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01002036 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002037 return( ret );
2038}
2039
Paul Bakker5121ce52009-01-03 21:22:43 +00002040/*
2041 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2042 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002043int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002044{
2045 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002047
Hanno Becker4bcb4912017-04-18 15:49:39 +01002048 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002050
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002051 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2052 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2053 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002054
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002055 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002056
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002057 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002058 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002059 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002060 goto cleanup;
2061 }
2062
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002063 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2064 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2065 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2066 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002067
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002068 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2069 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2070 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2071 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002072
2073 do
2074 {
2075 while( ( TU.p[0] & 1 ) == 0 )
2076 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002077 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002078
2079 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2080 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002081 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2082 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002083 }
2084
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002085 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2086 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002087 }
2088
2089 while( ( TV.p[0] & 1 ) == 0 )
2090 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002091 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002092
2093 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2094 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002095 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2096 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002097 }
2098
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002099 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2100 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002101 }
2102
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002103 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002104 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002105 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2106 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2107 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002108 }
2109 else
2110 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002111 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2112 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2113 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002114 }
2115 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002116 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002117
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002118 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2119 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002120
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002121 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2122 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002123
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002124 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002125
2126cleanup:
2127
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002128 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2129 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2130 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002131
2132 return( ret );
2133}
2134
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002135#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002136
Paul Bakker5121ce52009-01-03 21:22:43 +00002137static const int small_prime[] =
2138{
2139 3, 5, 7, 11, 13, 17, 19, 23,
2140 29, 31, 37, 41, 43, 47, 53, 59,
2141 61, 67, 71, 73, 79, 83, 89, 97,
2142 101, 103, 107, 109, 113, 127, 131, 137,
2143 139, 149, 151, 157, 163, 167, 173, 179,
2144 181, 191, 193, 197, 199, 211, 223, 227,
2145 229, 233, 239, 241, 251, 257, 263, 269,
2146 271, 277, 281, 283, 293, 307, 311, 313,
2147 317, 331, 337, 347, 349, 353, 359, 367,
2148 373, 379, 383, 389, 397, 401, 409, 419,
2149 421, 431, 433, 439, 443, 449, 457, 461,
2150 463, 467, 479, 487, 491, 499, 503, 509,
2151 521, 523, 541, 547, 557, 563, 569, 571,
2152 577, 587, 593, 599, 601, 607, 613, 617,
2153 619, 631, 641, 643, 647, 653, 659, 661,
2154 673, 677, 683, 691, 701, 709, 719, 727,
2155 733, 739, 743, 751, 757, 761, 769, 773,
2156 787, 797, 809, 811, 821, 823, 827, 829,
2157 839, 853, 857, 859, 863, 877, 881, 883,
2158 887, 907, 911, 919, 929, 937, 941, 947,
2159 953, 967, 971, 977, 983, 991, 997, -103
2160};
2161
2162/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002163 * Small divisors test (X must be positive)
2164 *
2165 * Return values:
2166 * 0: no small factor (possible prime, more tests needed)
2167 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002168 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002169 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002170 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002171static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002172{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002173 int ret = 0;
2174 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002175 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002176
Paul Bakker5121ce52009-01-03 21:22:43 +00002177 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002178 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002179
2180 for( i = 0; small_prime[i] > 0; i++ )
2181 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002182 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002183 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002185 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002186
2187 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002189 }
2190
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002191cleanup:
2192 return( ret );
2193}
2194
2195/*
2196 * Miller-Rabin pseudo-primality test (HAC 4.24)
2197 */
Janos Follath72d555d2018-09-03 14:45:23 +01002198static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002199 int (*f_rng)(void *, unsigned char *, size_t),
2200 void *p_rng )
2201{
Pascal Junodb99183d2015-03-11 16:49:45 +01002202 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002203 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002204 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002205
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2207 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002208
Paul Bakker5121ce52009-01-03 21:22:43 +00002209 /*
2210 * W = |X| - 1
2211 * R = W >> lsb( W )
2212 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002213 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2214 s = mbedtls_mpi_lsb( &W );
2215 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2216 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002217
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002218 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002219
Janos Follath72d555d2018-09-03 14:45:23 +01002220 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002221 {
2222 /*
2223 * pick a random A, 1 < A < |X| - 1
2224 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002225 count = 0;
2226 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002227 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002228
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002229 j = mbedtls_mpi_bitlen( &A );
2230 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002231 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002232 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002233 }
2234
2235 if (count++ > 30) {
Jens Wiklanderb2aa9382019-01-17 13:30:57 +01002236 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2237 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002238 }
2239
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002240 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2241 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002242
2243 /*
2244 * A = A^R mod |X|
2245 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002246 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002247
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002248 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2249 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002250 continue;
2251
2252 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002253 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002254 {
2255 /*
2256 * A = A * A mod |X|
2257 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002258 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2259 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002260
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002261 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002262 break;
2263
2264 j++;
2265 }
2266
2267 /*
2268 * not prime if A != |X| - 1 or A == 1
2269 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002270 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2271 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002272 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002273 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002274 break;
2275 }
2276 }
2277
2278cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002279 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2280 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002281
2282 return( ret );
2283}
2284
2285/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002286 * Pseudo-primality test: small factors, then Miller-Rabin
2287 */
Darryl Green94759f62018-10-16 15:09:19 +01002288static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002289 int (*f_rng)(void *, unsigned char *, size_t),
2290 void *p_rng )
2291{
2292 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002293 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002294
2295 XX.s = 1;
2296 XX.n = X->n;
2297 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2300 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2301 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002302
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002303 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002304 return( 0 );
2305
2306 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2307 {
2308 if( ret == 1 )
2309 return( 0 );
2310
2311 return( ret );
2312 }
2313
Janos Follath72d555d2018-09-03 14:45:23 +01002314 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2315}
2316
2317/*
2318 * Pseudo-primality test, error probability 2^-80
2319 */
2320int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2321 int (*f_rng)(void *, unsigned char *, size_t),
2322 void *p_rng )
2323{
2324 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002325}
2326
2327/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002328 * Prime number generation
2329 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002331 int (*f_rng)(void *, unsigned char *, size_t),
2332 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002333{
Paul Bakker23986e52011-04-24 08:57:21 +00002334 int ret;
2335 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002336 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002337 mbedtls_mpi_uint r;
2338 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002340 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2341 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002343 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002344
2345 n = BITS_TO_LIMBS( nbits );
2346
Janos Follath72d555d2018-09-03 14:45:23 +01002347 /*
2348 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2349 */
2350 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2351 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2352 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002354 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002355
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002356 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002357 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002358
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002359 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002360
2361 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002362
2363 if( dh_flag == 0 )
2364 {
Janos Follath72d555d2018-09-03 14:45:23 +01002365 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002366 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002368 goto cleanup;
2369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002370 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002371 }
2372 }
2373 else
2374 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002375 /*
2376 * An necessary condition for Y and X = 2Y + 1 to be prime
2377 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2378 * Make sure it is satisfied, while keeping X = 3 mod 4
2379 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002380
2381 X->p[0] |= 2;
2382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002384 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002386 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002387 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002388
2389 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002390 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2391 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002392
2393 while( 1 )
2394 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002395 /*
2396 * First, check small factors for X and Y
2397 * before doing Miller-Rabin on any of them
2398 */
2399 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2400 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002401 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2402 == 0 &&
2403 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2404 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002405 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002406 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002407 }
2408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002409 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002410 goto cleanup;
2411
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002412 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002413 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002414 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2415 * so up Y by 6 and X by 12.
2416 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002417 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2418 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002419 }
2420 }
2421
2422cleanup:
2423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002424 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002425
2426 return( ret );
2427}
2428
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002429#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002431#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002432
Paul Bakker23986e52011-04-24 08:57:21 +00002433#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002434
2435static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2436{
2437 { 693, 609, 21 },
2438 { 1764, 868, 28 },
2439 { 768454923, 542167814, 1 }
2440};
2441
Paul Bakker5121ce52009-01-03 21:22:43 +00002442/*
2443 * Checkup routine
2444 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002445int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002446{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002447 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002448 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002449
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002450 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2451 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002453 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002454 "EFE021C2645FD1DC586E69184AF4A31E" \
2455 "D5F53E93B5F123FA41680867BA110131" \
2456 "944FE7952E2517337780CB0DB80E61AA" \
2457 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002459 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002460 "B2E7EFD37075B9F03FF989C7C5051C20" \
2461 "34D2A323810251127E7BF8625A4F49A5" \
2462 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2463 "5B5C25763222FEFCCFC38B832366C29E" ) );
2464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002465 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002466 "0066A198186C18C10B2F5ED9B522752A" \
2467 "9830B69916E535C8F047518A889A43A5" \
2468 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2469
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002470 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002472 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002473 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2474 "9E857EA95A03512E2BAE7391688D264A" \
2475 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2476 "8001B72E848A38CAE1C65F78E56ABDEF" \
2477 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2478 "ECF677152EF804370C1A305CAF3B5BF1" \
2479 "30879B56C61DE584A0F53A2447A51E" ) );
2480
2481 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002482 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002484 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002485 {
2486 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002487 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002488
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002489 ret = 1;
2490 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002491 }
2492
2493 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002494 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002496 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002497
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002498 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002499 "256567336059E52CAE22925474705F39A94" ) );
2500
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002501 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002502 "6613F26162223DF488E9CD48CC132C7A" \
2503 "0AC93C701B001B092E4E5B9F73BCD27B" \
2504 "9EE50D0657C77F374E903CDFA4C642" ) );
2505
2506 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002507 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002509 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2510 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002511 {
2512 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002513 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002514
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002515 ret = 1;
2516 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002517 }
2518
2519 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002520 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002522 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002524 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002525 "36E139AEA55215609D2816998ED020BB" \
2526 "BD96C37890F65171D948E9BC7CBAA4D9" \
2527 "325D24D6A3C12710F10A09FA08AB87" ) );
2528
2529 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002530 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002531
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002532 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002533 {
2534 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002535 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002536
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002537 ret = 1;
2538 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002539 }
2540
2541 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002542 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002543
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002544 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002545
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002546 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002547 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2548 "C3DBA76456363A10869622EAC2DD84EC" \
2549 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2550
2551 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002552 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002554 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002555 {
2556 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002557 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002558
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002559 ret = 1;
2560 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002561 }
2562
2563 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002564 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002565
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002566 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002567 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002568
Paul Bakker66d5d072014-06-17 16:39:18 +02002569 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002570 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002571 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2572 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002573
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002574 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002576 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002577 {
2578 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002579 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002580
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002581 ret = 1;
2582 goto cleanup;
2583 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002584 }
2585
2586 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002587 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002588
Paul Bakker5121ce52009-01-03 21:22:43 +00002589cleanup:
2590
2591 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002592 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002593
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002594 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2595 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002596
2597 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002598 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002599
2600 return( ret );
2601}
2602
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002603#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002604
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002605#endif /* MBEDTLS_BIGNUM_C */