blob: 2b5e59c1c860c93a5c90de3d36b8e85d05dcecdd [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 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001704static int 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
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001710 if( T->n < N->n + 1 || T->p == NULL )
1711 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1712
Paul Bakker5121ce52009-01-03 21:22:43 +00001713 memset( T->p, 0, T->n * ciL );
1714
1715 d = T->p;
1716 n = N->n;
1717 m = ( B->n < n ) ? B->n : n;
1718
1719 for( i = 0; i < n; i++ )
1720 {
1721 /*
1722 * T = (T + u0*B + u1*N) / 2^biL
1723 */
1724 u0 = A->p[i];
1725 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1726
1727 mpi_mul_hlp( m, B->p, d, u0 );
1728 mpi_mul_hlp( n, N->p, d, u1 );
1729
1730 *d++ = u0; d[n + 1] = 0;
1731 }
1732
Paul Bakker66d5d072014-06-17 16:39:18 +02001733 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001734
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001735 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001736 mpi_sub_hlp( n, N->p, A->p );
1737 else
1738 /* prevent timing attacks */
1739 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001740
1741 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001742}
1743
1744/*
1745 * Montgomery reduction: A = A * R^-1 mod N
1746 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001747static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001748{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001749 mbedtls_mpi_uint z = 1;
1750 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001751
Paul Bakker8ddb6452013-02-27 14:56:33 +01001752 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001753 U.p = &z;
1754
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001755 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001756}
1757
1758/*
1759 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1760 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001761int 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 +00001762{
Paul Bakker23986e52011-04-24 08:57:21 +00001763 int ret;
1764 size_t wbits, wsize, one = 1;
1765 size_t i, j, nblimbs;
1766 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001767 mbedtls_mpi_uint ei, mm, state;
1768 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001769 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001770
Hanno Becker930ec7d2018-03-09 10:48:00 +00001771 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001772 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001773
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001774 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1775 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001776
1777 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001778 * Init temps and window size
1779 */
1780 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001781 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1782 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001783 memset( W, 0, sizeof( W ) );
1784
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001785 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001786
1787 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1788 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1789
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001790#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001791 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1792 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001793#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001794
Paul Bakker5121ce52009-01-03 21:22:43 +00001795 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001796 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1797 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1798 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001799
1800 /*
Paul Bakker50546922012-05-19 08:40:49 +00001801 * Compensate for negative A (and correct at the end)
1802 */
1803 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001804 if( neg )
1805 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001806 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001807 Apos.s = 1;
1808 A = &Apos;
1809 }
1810
1811 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001812 * If 1st call, pre-compute R^2 mod N
1813 */
1814 if( _RR == NULL || _RR->p == NULL )
1815 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1817 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1818 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001819
1820 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001821 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001822 }
1823 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001825
1826 /*
1827 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1828 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001829 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1830 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001831 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001832 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001833
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001834 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001835
1836 /*
1837 * X = R^2 * R^-1 mod N = R mod N
1838 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001839 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001840 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001841
1842 if( wsize > 1 )
1843 {
1844 /*
1845 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1846 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001847 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001848
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001849 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1850 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001851
1852 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001853 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001854
Paul Bakker5121ce52009-01-03 21:22:43 +00001855 /*
1856 * W[i] = W[i - 1] * W[1]
1857 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001858 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001859 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001860 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1861 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001862
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001863 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001864 }
1865 }
1866
1867 nblimbs = E->n;
1868 bufsize = 0;
1869 nbits = 0;
1870 wbits = 0;
1871 state = 0;
1872
1873 while( 1 )
1874 {
1875 if( bufsize == 0 )
1876 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001877 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001878 break;
1879
Paul Bakker0d7702c2013-10-29 16:18:35 +01001880 nblimbs--;
1881
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001883 }
1884
1885 bufsize--;
1886
1887 ei = (E->p[nblimbs] >> bufsize) & 1;
1888
1889 /*
1890 * skip leading 0s
1891 */
1892 if( ei == 0 && state == 0 )
1893 continue;
1894
1895 if( ei == 0 && state == 1 )
1896 {
1897 /*
1898 * out of window, square X
1899 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001900 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001901 continue;
1902 }
1903
1904 /*
1905 * add ei to current window
1906 */
1907 state = 2;
1908
1909 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001910 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001911
1912 if( nbits == wsize )
1913 {
1914 /*
1915 * X = X^wsize R^-1 mod N
1916 */
1917 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001918 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001919
1920 /*
1921 * X = X * W[wbits] R^-1 mod N
1922 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001923 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001924
1925 state--;
1926 nbits = 0;
1927 wbits = 0;
1928 }
1929 }
1930
1931 /*
1932 * process the remaining bits
1933 */
1934 for( i = 0; i < nbits; i++ )
1935 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001936 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001937
1938 wbits <<= 1;
1939
Paul Bakker66d5d072014-06-17 16:39:18 +02001940 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001941 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001942 }
1943
1944 /*
1945 * X = A^E * R * R^-1 mod N = A^E mod N
1946 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001947 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001948
Hanno Beckera4af1c42017-04-18 09:07:45 +01001949 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001950 {
1951 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001952 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001953 }
1954
Paul Bakker5121ce52009-01-03 21:22:43 +00001955cleanup:
1956
Paul Bakker66d5d072014-06-17 16:39:18 +02001957 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001958 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001959
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001960 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001961
Paul Bakker75a28602014-03-31 12:08:17 +02001962 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001964
1965 return( ret );
1966}
1967
Paul Bakker5121ce52009-01-03 21:22:43 +00001968/*
1969 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1970 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001971int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001972{
Paul Bakker23986e52011-04-24 08:57:21 +00001973 int ret;
1974 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001975 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001976
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001977 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001978
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001979 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1980 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001981
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001982 lz = mbedtls_mpi_lsb( &TA );
1983 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001984
Paul Bakker66d5d072014-06-17 16:39:18 +02001985 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001986 lz = lzt;
1987
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1989 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001990
Paul Bakker5121ce52009-01-03 21:22:43 +00001991 TA.s = TB.s = 1;
1992
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001993 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001994 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001995 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1996 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001997
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001998 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001999 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002000 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2001 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002002 }
2003 else
2004 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002005 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2006 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002007 }
2008 }
2009
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002010 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2011 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002012
2013cleanup:
2014
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002015 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002016
2017 return( ret );
2018}
2019
Paul Bakker33dc46b2014-04-30 16:11:39 +02002020/*
2021 * Fill X with size bytes of random.
2022 *
2023 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002024 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002025 * deterministic, eg for tests).
2026 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002027int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002028 int (*f_rng)(void *, unsigned char *, size_t),
2029 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002030{
Paul Bakker23986e52011-04-24 08:57:21 +00002031 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002032 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02002033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 if( size > MBEDTLS_MPI_MAX_SIZE )
2035 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002036
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002037 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2038 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002039
2040cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01002041 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002042 return( ret );
2043}
2044
Paul Bakker5121ce52009-01-03 21:22:43 +00002045/*
2046 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2047 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002048int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002049{
2050 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002051 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002052
Hanno Becker4bcb4912017-04-18 15:49:39 +01002053 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002054 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002055
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002056 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2057 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2058 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002061
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002062 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002063 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002064 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002065 goto cleanup;
2066 }
2067
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002068 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2069 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2070 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2071 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002072
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002073 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2074 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2075 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2076 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002077
2078 do
2079 {
2080 while( ( TU.p[0] & 1 ) == 0 )
2081 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002082 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002083
2084 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2085 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002086 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2087 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002088 }
2089
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002090 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2091 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002092 }
2093
2094 while( ( TV.p[0] & 1 ) == 0 )
2095 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002096 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002097
2098 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2099 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002100 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2101 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002102 }
2103
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002104 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2105 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002106 }
2107
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002108 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002109 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002110 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2111 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2112 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002113 }
2114 else
2115 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002116 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2117 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2118 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002119 }
2120 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002121 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002123 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2124 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002125
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002126 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2127 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002129 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002130
2131cleanup:
2132
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002133 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2134 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2135 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002136
2137 return( ret );
2138}
2139
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002140#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002141
Paul Bakker5121ce52009-01-03 21:22:43 +00002142static const int small_prime[] =
2143{
2144 3, 5, 7, 11, 13, 17, 19, 23,
2145 29, 31, 37, 41, 43, 47, 53, 59,
2146 61, 67, 71, 73, 79, 83, 89, 97,
2147 101, 103, 107, 109, 113, 127, 131, 137,
2148 139, 149, 151, 157, 163, 167, 173, 179,
2149 181, 191, 193, 197, 199, 211, 223, 227,
2150 229, 233, 239, 241, 251, 257, 263, 269,
2151 271, 277, 281, 283, 293, 307, 311, 313,
2152 317, 331, 337, 347, 349, 353, 359, 367,
2153 373, 379, 383, 389, 397, 401, 409, 419,
2154 421, 431, 433, 439, 443, 449, 457, 461,
2155 463, 467, 479, 487, 491, 499, 503, 509,
2156 521, 523, 541, 547, 557, 563, 569, 571,
2157 577, 587, 593, 599, 601, 607, 613, 617,
2158 619, 631, 641, 643, 647, 653, 659, 661,
2159 673, 677, 683, 691, 701, 709, 719, 727,
2160 733, 739, 743, 751, 757, 761, 769, 773,
2161 787, 797, 809, 811, 821, 823, 827, 829,
2162 839, 853, 857, 859, 863, 877, 881, 883,
2163 887, 907, 911, 919, 929, 937, 941, 947,
2164 953, 967, 971, 977, 983, 991, 997, -103
2165};
2166
2167/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002168 * Small divisors test (X must be positive)
2169 *
2170 * Return values:
2171 * 0: no small factor (possible prime, more tests needed)
2172 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002173 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002174 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002175 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002176static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002177{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002178 int ret = 0;
2179 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002180 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002181
Paul Bakker5121ce52009-01-03 21:22:43 +00002182 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002183 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002184
2185 for( i = 0; small_prime[i] > 0; i++ )
2186 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002187 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002188 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002189
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002190 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002191
2192 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002193 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002194 }
2195
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002196cleanup:
2197 return( ret );
2198}
2199
2200/*
2201 * Miller-Rabin pseudo-primality test (HAC 4.24)
2202 */
Janos Follath72d555d2018-09-03 14:45:23 +01002203static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002204 int (*f_rng)(void *, unsigned char *, size_t),
2205 void *p_rng )
2206{
Pascal Junodb99183d2015-03-11 16:49:45 +01002207 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002208 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002209 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002210
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002211 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2212 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002213
Paul Bakker5121ce52009-01-03 21:22:43 +00002214 /*
2215 * W = |X| - 1
2216 * R = W >> lsb( W )
2217 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002218 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2219 s = mbedtls_mpi_lsb( &W );
2220 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2221 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002222
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002223 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002224
Janos Follath72d555d2018-09-03 14:45:23 +01002225 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002226 {
2227 /*
2228 * pick a random A, 1 < A < |X| - 1
2229 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002230 count = 0;
2231 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002232 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002233
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002234 j = mbedtls_mpi_bitlen( &A );
2235 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002236 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002237 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002238 }
2239
2240 if (count++ > 30) {
Jens Wiklanderb2aa9382019-01-17 13:30:57 +01002241 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2242 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002243 }
2244
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002245 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2246 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002247
2248 /*
2249 * A = A^R mod |X|
2250 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002251 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002252
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002253 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2254 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002255 continue;
2256
2257 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002258 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002259 {
2260 /*
2261 * A = A * A mod |X|
2262 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002263 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2264 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002265
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002266 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002267 break;
2268
2269 j++;
2270 }
2271
2272 /*
2273 * not prime if A != |X| - 1 or A == 1
2274 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002275 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2276 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002277 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002278 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002279 break;
2280 }
2281 }
2282
2283cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002284 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2285 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002286
2287 return( ret );
2288}
2289
2290/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002291 * Pseudo-primality test: small factors, then Miller-Rabin
2292 */
Darryl Green94759f62018-10-16 15:09:19 +01002293static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002294 int (*f_rng)(void *, unsigned char *, size_t),
2295 void *p_rng )
2296{
2297 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002298 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002299
2300 XX.s = 1;
2301 XX.n = X->n;
2302 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002303
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002304 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2305 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2306 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002307
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002308 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002309 return( 0 );
2310
2311 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2312 {
2313 if( ret == 1 )
2314 return( 0 );
2315
2316 return( ret );
2317 }
2318
Janos Follath72d555d2018-09-03 14:45:23 +01002319 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2320}
2321
2322/*
2323 * Pseudo-primality test, error probability 2^-80
2324 */
2325int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2326 int (*f_rng)(void *, unsigned char *, size_t),
2327 void *p_rng )
2328{
2329 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002330}
2331
2332/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002333 * Prime number generation
2334 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002336 int (*f_rng)(void *, unsigned char *, size_t),
2337 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002338{
Paul Bakker23986e52011-04-24 08:57:21 +00002339 int ret;
2340 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002341 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 mbedtls_mpi_uint r;
2343 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002345 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2346 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002347
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002348 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002349
2350 n = BITS_TO_LIMBS( nbits );
2351
Janos Follath72d555d2018-09-03 14:45:23 +01002352 /*
2353 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2354 */
2355 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2356 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2357 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2358
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002361 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002362 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002363
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002364 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002365
2366 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002367
2368 if( dh_flag == 0 )
2369 {
Janos Follath72d555d2018-09-03 14:45:23 +01002370 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002371 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002372 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002373 goto cleanup;
2374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002375 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002376 }
2377 }
2378 else
2379 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002380 /*
2381 * An necessary condition for Y and X = 2Y + 1 to be prime
2382 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2383 * Make sure it is satisfied, while keeping X = 3 mod 4
2384 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002385
2386 X->p[0] |= 2;
2387
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002388 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002389 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002390 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002391 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002392 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002393
2394 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002395 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2396 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002397
2398 while( 1 )
2399 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002400 /*
2401 * First, check small factors for X and Y
2402 * before doing Miller-Rabin on any of them
2403 */
2404 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2405 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002406 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2407 == 0 &&
2408 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2409 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002410 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002411 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002412 }
2413
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002414 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002415 goto cleanup;
2416
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002417 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002418 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002419 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2420 * so up Y by 6 and X by 12.
2421 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002422 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2423 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002424 }
2425 }
2426
2427cleanup:
2428
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002429 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002430
2431 return( ret );
2432}
2433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002435
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002436#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002437
Paul Bakker23986e52011-04-24 08:57:21 +00002438#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002439
2440static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2441{
2442 { 693, 609, 21 },
2443 { 1764, 868, 28 },
2444 { 768454923, 542167814, 1 }
2445};
2446
Paul Bakker5121ce52009-01-03 21:22:43 +00002447/*
2448 * Checkup routine
2449 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002450int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002451{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002452 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002453 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002455 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2456 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002457
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002458 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002459 "EFE021C2645FD1DC586E69184AF4A31E" \
2460 "D5F53E93B5F123FA41680867BA110131" \
2461 "944FE7952E2517337780CB0DB80E61AA" \
2462 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2463
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002464 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002465 "B2E7EFD37075B9F03FF989C7C5051C20" \
2466 "34D2A323810251127E7BF8625A4F49A5" \
2467 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2468 "5B5C25763222FEFCCFC38B832366C29E" ) );
2469
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002470 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002471 "0066A198186C18C10B2F5ED9B522752A" \
2472 "9830B69916E535C8F047518A889A43A5" \
2473 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2474
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002476
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002477 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002478 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2479 "9E857EA95A03512E2BAE7391688D264A" \
2480 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2481 "8001B72E848A38CAE1C65F78E56ABDEF" \
2482 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2483 "ECF677152EF804370C1A305CAF3B5BF1" \
2484 "30879B56C61DE584A0F53A2447A51E" ) );
2485
2486 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002487 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002489 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002490 {
2491 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002492 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002493
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002494 ret = 1;
2495 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002496 }
2497
2498 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002499 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002500
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002501 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002503 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002504 "256567336059E52CAE22925474705F39A94" ) );
2505
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002506 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002507 "6613F26162223DF488E9CD48CC132C7A" \
2508 "0AC93C701B001B092E4E5B9F73BCD27B" \
2509 "9EE50D0657C77F374E903CDFA4C642" ) );
2510
2511 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002512 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002514 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2515 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002516 {
2517 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002518 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002519
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002520 ret = 1;
2521 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002522 }
2523
2524 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002525 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002526
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002527 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002529 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002530 "36E139AEA55215609D2816998ED020BB" \
2531 "BD96C37890F65171D948E9BC7CBAA4D9" \
2532 "325D24D6A3C12710F10A09FA08AB87" ) );
2533
2534 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002535 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002536
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002537 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002538 {
2539 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002540 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002541
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002542 ret = 1;
2543 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002544 }
2545
2546 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002547 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002548
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002549 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002550
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002551 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002552 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2553 "C3DBA76456363A10869622EAC2DD84EC" \
2554 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2555
2556 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002557 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002558
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002559 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002560 {
2561 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002563
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002564 ret = 1;
2565 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002566 }
2567
2568 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002569 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002570
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002571 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002572 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002573
Paul Bakker66d5d072014-06-17 16:39:18 +02002574 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002575 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002576 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2577 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002578
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002579 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002580
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002581 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002582 {
2583 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002584 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002585
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002586 ret = 1;
2587 goto cleanup;
2588 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002589 }
2590
2591 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002592 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002593
Paul Bakker5121ce52009-01-03 21:22:43 +00002594cleanup:
2595
2596 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002597 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002598
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002599 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2600 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002601
2602 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002603 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002604
2605 return( ret );
2606}
2607
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002608#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002609
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002610#endif /* MBEDTLS_BIGNUM_C */