blob: 26784f9dadd2cd9bc514d4bfee97631db857556a [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000048
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <string.h>
50
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000052#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020053#else
Rich Evans00ab4702015-02-06 13:43:58 +000054#include <stdio.h>
55#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020057#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020059#endif
60
Paul Bakker34617722014-06-13 17:20:13 +020061/* Implementation that should never be optimized out by the compiler */
Alexey Skalozube17a8da2016-01-13 17:19:33 +020062static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) {
Alexey Skalozub3d53f412016-01-13 16:53:40 +020063 volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0;
Paul Bakker34617722014-06-13 17:20:13 +020064}
65
Hanno Becker88807112017-10-18 12:41:30 +010066/* Implementation that should never be optimized out by the compiler */
67static void mbedtls_zeroize( void *v, size_t n ) {
68 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
69}
70
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000072#define biL (ciL << 3) /* bits in limb */
73#define biH (ciL << 2) /* half limb size */
74
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010075#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
76
Paul Bakker5121ce52009-01-03 21:22:43 +000077/*
78 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020079 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000080 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020081#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
82#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000083
84/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000085 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000086 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020087void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000088{
Paul Bakker6c591fa2011-05-05 11:49:20 +000089 if( X == NULL )
90 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000091
Paul Bakker6c591fa2011-05-05 11:49:20 +000092 X->s = 1;
93 X->n = 0;
94 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000095}
96
97/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000098 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000099 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000101{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000102 if( X == NULL )
103 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000104
Paul Bakker6c591fa2011-05-05 11:49:20 +0000105 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000106 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200107 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200108 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000109 }
110
Paul Bakker6c591fa2011-05-05 11:49:20 +0000111 X->s = 1;
112 X->n = 0;
113 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000114}
115
116/*
117 * Enlarge to the specified number of limbs
118 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000120{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200123 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200124 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000125
Paul Bakker5121ce52009-01-03 21:22:43 +0000126 if( X->n < nblimbs )
127 {
Simon Butcher29176892016-05-20 00:19:09 +0100128 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200129 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000130
Paul Bakker5121ce52009-01-03 21:22:43 +0000131 if( X->p != NULL )
132 {
133 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200134 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000136 }
137
138 X->n = nblimbs;
139 X->p = p;
140 }
141
142 return( 0 );
143}
144
145/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100146 * Resize down as much as possible,
147 * while keeping at least the specified number of limbs
148 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100150{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152 size_t i;
153
Gilles Peskine6a269672020-01-20 21:17:43 +0100154 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100155 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine774c1632020-01-21 13:59:51 +0100157 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100158
159 for( i = X->n - 1; i > 0; i-- )
160 if( X->p[i] != 0 )
161 break;
162 i++;
163
164 if( i < nblimbs )
165 i = nblimbs;
166
Simon Butcher29176892016-05-20 00:19:09 +0100167 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200168 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100169
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100170 if( X->p != NULL )
171 {
172 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200173 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175 }
176
177 X->n = i;
178 X->p = p;
179
180 return( 0 );
181}
182
183/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000184 * Copy the contents of Y into X
185 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000187{
Paul Bakker23986e52011-04-24 08:57:21 +0000188 int ret;
189 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000190
191 if( X == Y )
192 return( 0 );
193
Gilles Peskine2aeab872020-01-20 21:12:50 +0100194 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200195 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200196 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200197 return( 0 );
198 }
199
Paul Bakker5121ce52009-01-03 21:22:43 +0000200 for( i = Y->n - 1; i > 0; i-- )
201 if( Y->p[i] != 0 )
202 break;
203 i++;
204
205 X->s = Y->s;
206
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000208
209 memset( X->p, 0, X->n * ciL );
210 memcpy( X->p, Y->p, i * ciL );
211
212cleanup:
213
214 return( ret );
215}
216
217/*
218 * Swap the contents of X and Y
219 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000221{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000223
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200224 memcpy( &T, X, sizeof( mbedtls_mpi ) );
225 memcpy( X, Y, sizeof( mbedtls_mpi ) );
226 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000227}
228
229/*
Gilles Peskine3c44c652020-06-04 19:14:58 +0200230 * Conditionally assign dest = src, without leaking information
231 * about whether the assignment was made or not.
232 * dest and src must be arrays of limbs of size n.
233 * assign must be 0 or 1.
234 */
235static void mpi_safe_cond_assign( size_t n,
236 mbedtls_mpi_uint *dest,
237 const mbedtls_mpi_uint *src,
238 unsigned char assign )
239{
240 size_t i;
241 for( i = 0; i < n; i++ )
242 dest[i] = dest[i] * ( 1 - assign ) + src[i] * assign;
243}
244
245/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100246 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100247 * about whether the assignment was made or not.
248 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100249 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100251{
252 int ret = 0;
253 size_t i;
254
Pascal Junodb99183d2015-03-11 16:49:45 +0100255 /* make sure assign is 0 or 1 in a time-constant manner */
256 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100257
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200258 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100259
Paul Bakker66d5d072014-06-17 16:39:18 +0200260 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100261
Gilles Peskine3c44c652020-06-04 19:14:58 +0200262 mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100263
Gilles Peskine3c44c652020-06-04 19:14:58 +0200264 for( i = Y->n; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200265 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100266
267cleanup:
268 return( ret );
269}
270
271/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100272 * Conditionally swap X and Y, without leaking information
273 * about whether the swap was made or not.
274 * Here it is not ok to simply swap the pointers, which whould lead to
275 * different memory access patterns when X and Y are used afterwards.
276 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200277int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100278{
279 int ret, s;
280 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100282
283 if( X == Y )
284 return( 0 );
285
Pascal Junodb99183d2015-03-11 16:49:45 +0100286 /* make sure swap is 0 or 1 in a time-constant manner */
287 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100288
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200289 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
290 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100291
292 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200293 X->s = X->s * ( 1 - swap ) + Y->s * swap;
294 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100295
296
297 for( i = 0; i < X->n; i++ )
298 {
299 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200300 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
301 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100302 }
303
304cleanup:
305 return( ret );
306}
307
308/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000309 * Set value from integer
310 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200311int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000312{
313 int ret;
314
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000316 memset( X->p, 0, X->n * ciL );
317
318 X->p[0] = ( z < 0 ) ? -z : z;
319 X->s = ( z < 0 ) ? -1 : 1;
320
321cleanup:
322
323 return( ret );
324}
325
326/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000327 * Get a specific bit
328 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200329int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000330{
331 if( X->n * biL <= pos )
332 return( 0 );
333
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200334 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000335}
336
Gilles Peskine220cc172018-11-20 16:47:47 +0100337/* Get a specific byte, without range checks. */
338#define GET_BYTE( X, i ) \
339 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
340
Paul Bakker2f5947e2011-05-18 15:47:11 +0000341/*
342 * Set a bit to a specific value of 0 or 1
343 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000345{
346 int ret = 0;
347 size_t off = pos / biL;
348 size_t idx = pos % biL;
349
350 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200352
Paul Bakker2f5947e2011-05-18 15:47:11 +0000353 if( X->n * biL <= pos )
354 {
355 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200356 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200358 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000359 }
360
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200361 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
362 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000363
364cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200365
Paul Bakker2f5947e2011-05-18 15:47:11 +0000366 return( ret );
367}
368
369/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200370 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000371 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200372size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000373{
Paul Bakker23986e52011-04-24 08:57:21 +0000374 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000375
376 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000377 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000378 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
379 return( count );
380
381 return( 0 );
382}
383
384/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000385 * Count leading zero bits in a given integer
386 */
387static size_t mbedtls_clz( const mbedtls_mpi_uint x )
388{
389 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100390 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000391
392 for( j = 0; j < biL; j++ )
393 {
394 if( x & mask ) break;
395
396 mask >>= 1;
397 }
398
399 return j;
400}
401
402/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200403 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000404 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200405size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000406{
Paul Bakker23986e52011-04-24 08:57:21 +0000407 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000408
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200409 if( X->n == 0 )
410 return( 0 );
411
Paul Bakker5121ce52009-01-03 21:22:43 +0000412 for( i = X->n - 1; i > 0; i-- )
413 if( X->p[i] != 0 )
414 break;
415
Simon Butcher15b15d12015-11-26 19:35:03 +0000416 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
Paul Bakker23986e52011-04-24 08:57:21 +0000418 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000419}
420
421/*
422 * Return the total size in bytes
423 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000425{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200426 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000427}
428
429/*
430 * Convert an ASCII character to digit value
431 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000433{
434 *d = 255;
435
436 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
437 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
438 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
439
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200440 if( *d >= (mbedtls_mpi_uint) radix )
441 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
443 return( 0 );
444}
445
446/*
447 * Import from an ASCII string
448 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000450{
Paul Bakker23986e52011-04-24 08:57:21 +0000451 int ret;
452 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453 mbedtls_mpi_uint d;
454 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000455
456 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000460
Paul Bakkerff60ee62010-03-16 21:09:09 +0000461 slen = strlen( s );
462
Paul Bakker5121ce52009-01-03 21:22:43 +0000463 if( radix == 16 )
464 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100465 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200466 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
467
Paul Bakkerff60ee62010-03-16 21:09:09 +0000468 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
471 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000472
Paul Bakker23986e52011-04-24 08:57:21 +0000473 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 {
Paul Bakker23986e52011-04-24 08:57:21 +0000475 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000476 {
477 X->s = -1;
478 break;
479 }
480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200482 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483 }
484 }
485 else
486 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000488
Paul Bakkerff60ee62010-03-16 21:09:09 +0000489 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000490 {
491 if( i == 0 && s[i] == '-' )
492 {
493 X->s = -1;
494 continue;
495 }
496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
498 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000499
500 if( X->s == 1 )
501 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000503 }
504 else
505 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200506 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000507 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000508 }
509 }
510
511cleanup:
512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000514
515 return( ret );
516}
517
518/*
Ron Eldore6cbfc32018-11-20 14:07:01 +0200519 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000520 */
Ron Eldore6cbfc32018-11-20 14:07:01 +0200521static int mpi_write_hlp( mbedtls_mpi *X, int radix,
522 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000523{
524 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525 mbedtls_mpi_uint r;
Ron Eldore6cbfc32018-11-20 14:07:01 +0200526 size_t length = 0;
527 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000528
Ron Eldore6cbfc32018-11-20 14:07:01 +0200529 do
530 {
531 if( length >= buflen )
532 {
533 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
534 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000535
Ron Eldore6cbfc32018-11-20 14:07:01 +0200536 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
537 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
538 /*
539 * Write the residue in the current position, as an ASCII character.
540 */
541 if( r < 0xA )
542 *(--p_end) = (char)( '0' + r );
543 else
544 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000545
Ron Eldore6cbfc32018-11-20 14:07:01 +0200546 length++;
547 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000548
Ron Eldore6cbfc32018-11-20 14:07:01 +0200549 memmove( *p, p_end, length );
550 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000551
552cleanup:
553
554 return( ret );
555}
556
557/*
558 * Export into an ASCII string
559 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100560int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
561 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000562{
Paul Bakker23986e52011-04-24 08:57:21 +0000563 int ret = 0;
564 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000565 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000567
568 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200569 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000570
Hanno Beckera277d4c2019-02-04 09:45:07 +0000571 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
572 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
573 * `n`. If radix > 4, this might be a strict
574 * overapproximation of the number of
575 * radix-adic digits needed to present `n`. */
576 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
577 * present `n`. */
578
Janos Follath216e7382019-03-06 13:43:02 +0000579 n += 1; /* Terminating null byte */
Hanno Beckera277d4c2019-02-04 09:45:07 +0000580 n += 1; /* Compensate for the divisions above, which round down `n`
581 * in case it's not even. */
582 n += 1; /* Potential '-'-sign. */
583 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
584 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000585
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100586 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000587 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100588 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200589 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000590 }
591
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100592 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200593 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000594
595 if( X->s == -1 )
Hanno Beckereff335d2019-02-01 16:41:30 +0000596 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000597 *p++ = '-';
Hanno Beckereff335d2019-02-01 16:41:30 +0000598 buflen--;
599 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000600
601 if( radix == 16 )
602 {
Paul Bakker23986e52011-04-24 08:57:21 +0000603 int c;
604 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000605
Paul Bakker23986e52011-04-24 08:57:21 +0000606 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000607 {
Paul Bakker23986e52011-04-24 08:57:21 +0000608 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000609 {
Paul Bakker23986e52011-04-24 08:57:21 +0000610 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000611
Paul Bakker6c343d72014-07-10 14:36:19 +0200612 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000613 continue;
614
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000615 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000616 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000617 k = 1;
618 }
619 }
620 }
621 else
622 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200623 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000624
625 if( T.s == -1 )
626 T.s = 1;
627
Ron Eldore6cbfc32018-11-20 14:07:01 +0200628 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000629 }
630
631 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100632 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000633
634cleanup:
635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200636 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000637
638 return( ret );
639}
640
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000642/*
643 * Read X from an opened file
644 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200645int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000646{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200647 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000648 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000649 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000650 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000651 * Buffer should have space for (short) label and decimal formatted MPI,
652 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000653 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200654 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000655
656 memset( s, 0, sizeof( s ) );
657 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000659
660 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000661 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000663
Hanno Beckerb2034b72017-04-26 11:46:46 +0100664 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
665 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000666
667 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100668 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000669 if( mpi_get_digit( &d, radix, *p ) != 0 )
670 break;
671
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000673}
674
675/*
676 * Write X into an opened file (or stdout if fout == NULL)
677 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000679{
Paul Bakker23986e52011-04-24 08:57:21 +0000680 int ret;
681 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000682 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000683 * Buffer should have space for (short) label and decimal formatted MPI,
684 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000685 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200686 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000687
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100688 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000689
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100690 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
692 if( p == NULL ) p = "";
693
694 plen = strlen( p );
695 slen = strlen( s );
696 s[slen++] = '\r';
697 s[slen++] = '\n';
698
699 if( fout != NULL )
700 {
701 if( fwrite( p, 1, plen, fout ) != plen ||
702 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000704 }
705 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
708cleanup:
709
710 return( ret );
711}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200712#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000713
714/*
715 * Import X from unsigned binary data, big endian
716 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200717int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000718{
Paul Bakker23986e52011-04-24 08:57:21 +0000719 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100720 size_t i, j;
721 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000722
Hanno Becker073c1992017-10-17 15:17:27 +0100723 /* Ensure that target MPI has exactly the necessary number of limbs */
724 if( X->n != limbs )
725 {
726 mbedtls_mpi_free( X );
727 mbedtls_mpi_init( X );
728 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
729 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000730
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000732
Hanno Becker073c1992017-10-17 15:17:27 +0100733 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200734 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000735
736cleanup:
737
738 return( ret );
739}
740
741/*
742 * Export X into unsigned binary data, big endian
743 */
Gilles Peskine220cc172018-11-20 16:47:47 +0100744int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
745 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000746{
Gilles Peskine220cc172018-11-20 16:47:47 +0100747 size_t stored_bytes = X->n * ciL;
748 size_t bytes_to_copy;
749 unsigned char *p;
750 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000751
Gilles Peskine220cc172018-11-20 16:47:47 +0100752 if( stored_bytes < buflen )
753 {
754 /* There is enough space in the output buffer. Write initial
755 * null bytes and record the position at which to start
756 * writing the significant bytes. In this case, the execution
757 * trace of this function does not depend on the value of the
758 * number. */
759 bytes_to_copy = stored_bytes;
760 p = buf + buflen - stored_bytes;
761 memset( buf, 0, buflen - stored_bytes );
762 }
763 else
764 {
765 /* The output buffer is smaller than the allocated size of X.
766 * However X may fit if its leading bytes are zero. */
767 bytes_to_copy = buflen;
768 p = buf;
769 for( i = bytes_to_copy; i < stored_bytes; i++ )
770 {
771 if( GET_BYTE( X, i ) != 0 )
772 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
773 }
774 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000775
Gilles Peskine220cc172018-11-20 16:47:47 +0100776 for( i = 0; i < bytes_to_copy; i++ )
777 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000778
779 return( 0 );
780}
781
782/*
783 * Left-shift: X <<= count
784 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200785int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000786{
Paul Bakker23986e52011-04-24 08:57:21 +0000787 int ret;
788 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200789 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000790
791 v0 = count / (biL );
792 t1 = count & (biL - 1);
793
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200794 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000795
Paul Bakkerf9688572011-05-05 10:00:45 +0000796 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200797 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000798
799 ret = 0;
800
801 /*
802 * shift by count / limb_size
803 */
804 if( v0 > 0 )
805 {
Paul Bakker23986e52011-04-24 08:57:21 +0000806 for( i = X->n; i > v0; i-- )
807 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000808
Paul Bakker23986e52011-04-24 08:57:21 +0000809 for( ; i > 0; i-- )
810 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000811 }
812
813 /*
814 * shift by count % limb_size
815 */
816 if( t1 > 0 )
817 {
818 for( i = v0; i < X->n; i++ )
819 {
820 r1 = X->p[i] >> (biL - t1);
821 X->p[i] <<= t1;
822 X->p[i] |= r0;
823 r0 = r1;
824 }
825 }
826
827cleanup:
828
829 return( ret );
830}
831
832/*
833 * Right-shift: X >>= count
834 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200835int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000836{
Paul Bakker23986e52011-04-24 08:57:21 +0000837 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200838 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000839
840 v0 = count / biL;
841 v1 = count & (biL - 1);
842
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100843 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200844 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100845
Paul Bakker5121ce52009-01-03 21:22:43 +0000846 /*
847 * shift by count / limb_size
848 */
849 if( v0 > 0 )
850 {
851 for( i = 0; i < X->n - v0; i++ )
852 X->p[i] = X->p[i + v0];
853
854 for( ; i < X->n; i++ )
855 X->p[i] = 0;
856 }
857
858 /*
859 * shift by count % limb_size
860 */
861 if( v1 > 0 )
862 {
Paul Bakker23986e52011-04-24 08:57:21 +0000863 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000864 {
Paul Bakker23986e52011-04-24 08:57:21 +0000865 r1 = X->p[i - 1] << (biL - v1);
866 X->p[i - 1] >>= v1;
867 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000868 r0 = r1;
869 }
870 }
871
872 return( 0 );
873}
874
875/*
876 * Compare unsigned values
877 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200878int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000879{
Paul Bakker23986e52011-04-24 08:57:21 +0000880 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000881
Paul Bakker23986e52011-04-24 08:57:21 +0000882 for( i = X->n; i > 0; i-- )
883 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000884 break;
885
Paul Bakker23986e52011-04-24 08:57:21 +0000886 for( j = Y->n; j > 0; j-- )
887 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000888 break;
889
Paul Bakker23986e52011-04-24 08:57:21 +0000890 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000891 return( 0 );
892
893 if( i > j ) return( 1 );
894 if( j > i ) return( -1 );
895
Paul Bakker23986e52011-04-24 08:57:21 +0000896 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000897 {
Paul Bakker23986e52011-04-24 08:57:21 +0000898 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
899 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000900 }
901
902 return( 0 );
903}
904
905/*
906 * Compare signed values
907 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200908int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000909{
Paul Bakker23986e52011-04-24 08:57:21 +0000910 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000911
Paul Bakker23986e52011-04-24 08:57:21 +0000912 for( i = X->n; i > 0; i-- )
913 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000914 break;
915
Paul Bakker23986e52011-04-24 08:57:21 +0000916 for( j = Y->n; j > 0; j-- )
917 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000918 break;
919
Paul Bakker23986e52011-04-24 08:57:21 +0000920 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000921 return( 0 );
922
923 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000924 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000925
926 if( X->s > 0 && Y->s < 0 ) return( 1 );
927 if( Y->s > 0 && X->s < 0 ) return( -1 );
928
Paul Bakker23986e52011-04-24 08:57:21 +0000929 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000930 {
Paul Bakker23986e52011-04-24 08:57:21 +0000931 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
932 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000933 }
934
935 return( 0 );
936}
937
Janos Follath3173a532019-10-14 09:09:32 +0100938/** Decide if an integer is less than the other, without branches.
939 *
940 * \param x First integer.
941 * \param y Second integer.
942 *
943 * \return 1 if \p x is less than \p y, 0 otherwise
944 */
Janos Follathc3b376e2019-10-11 14:21:53 +0100945static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
946 const mbedtls_mpi_uint y )
Janos Follathe0187b92019-09-05 14:47:19 +0100947{
948 mbedtls_mpi_uint ret;
949 mbedtls_mpi_uint cond;
950
951 /*
952 * Check if the most significant bits (MSB) of the operands are different.
953 */
954 cond = ( x ^ y );
955 /*
956 * If the MSB are the same then the difference x-y will be negative (and
957 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
958 */
959 ret = ( x - y ) & ~cond;
960 /*
961 * If the MSB are different, then the operand with the MSB of 1 is the
962 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
963 * the MSB of y is 0.)
964 */
965 ret |= y & cond;
966
967
Janos Follathdb9f4492019-10-14 08:59:14 +0100968 ret = ret >> ( biL - 1 );
Janos Follathe0187b92019-09-05 14:47:19 +0100969
Janos Follath58239612019-10-29 15:08:46 +0000970 return (unsigned) ret;
Janos Follathe0187b92019-09-05 14:47:19 +0100971}
972
973/*
974 * Compare signed values in constant time
975 */
Janos Follathc3b376e2019-10-11 14:21:53 +0100976int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
977 unsigned *ret )
Janos Follathe0187b92019-09-05 14:47:19 +0100978{
979 size_t i;
Janos Follatha2b9a962019-10-28 12:23:18 +0000980 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath8ec2a952019-10-28 12:31:34 +0000981 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathe0187b92019-09-05 14:47:19 +0100982
983 if( X->n != Y->n )
984 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
985
986 /*
Janos Follath51ed14e2019-10-28 12:12:15 +0000987 * Set sign_N to 1 if N >= 0, 0 if N < 0.
988 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathe0187b92019-09-05 14:47:19 +0100989 */
Janos Follath8ec2a952019-10-28 12:31:34 +0000990 X_is_negative = ( X->s & 2 ) >> 1;
991 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follathc3b376e2019-10-11 14:21:53 +0100992
993 /*
994 * If the signs are different, then the positive operand is the bigger.
Janos Follath8ec2a952019-10-28 12:31:34 +0000995 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
996 * is false if X is positive (X_is_negative == 0).
Janos Follathc3b376e2019-10-11 14:21:53 +0100997 */
Janos Follath8ec2a952019-10-28 12:31:34 +0000998 cond = ( X_is_negative ^ Y_is_negative );
999 *ret = cond & X_is_negative;
Janos Follathc3b376e2019-10-11 14:21:53 +01001000
1001 /*
Janos Follatha2b9a962019-10-28 12:23:18 +00001002 * This is a constant-time function. We might have the result, but we still
Janos Follathc3b376e2019-10-11 14:21:53 +01001003 * need to go through the loop. Record if we have the result already.
1004 */
Janos Follathe0187b92019-09-05 14:47:19 +01001005 done = cond;
1006
1007 for( i = X->n; i > 0; i-- )
1008 {
1009 /*
Janos Follathb4edac52019-11-05 12:24:52 +00001010 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1011 * X and Y are negative.
Janos Follathc3b376e2019-10-11 14:21:53 +01001012 *
1013 * Again even if we can make a decision, we just mark the result and
1014 * the fact that we are done and continue looping.
Janos Follathe0187b92019-09-05 14:47:19 +01001015 */
Janos Follathb4edac52019-11-05 12:24:52 +00001016 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1017 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathcff9e6e2019-10-28 12:37:21 +00001018 done |= cond;
Janos Follathe0187b92019-09-05 14:47:19 +01001019
1020 /*
Janos Follathb4edac52019-11-05 12:24:52 +00001021 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1022 * X and Y are positive.
Janos Follathc3b376e2019-10-11 14:21:53 +01001023 *
1024 * Again even if we can make a decision, we just mark the result and
1025 * the fact that we are done and continue looping.
Janos Follathe0187b92019-09-05 14:47:19 +01001026 */
Janos Follathb4edac52019-11-05 12:24:52 +00001027 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1028 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathcff9e6e2019-10-28 12:37:21 +00001029 done |= cond;
Janos Follathe0187b92019-09-05 14:47:19 +01001030 }
1031
1032 return( 0 );
1033}
1034
Paul Bakker5121ce52009-01-03 21:22:43 +00001035/*
1036 * Compare signed values
1037 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001038int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001039{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001040 mbedtls_mpi Y;
1041 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001042
1043 *p = ( z < 0 ) ? -z : z;
1044 Y.s = ( z < 0 ) ? -1 : 1;
1045 Y.n = 1;
1046 Y.p = p;
1047
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001048 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001049}
1050
1051/*
1052 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1053 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001054int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001055{
Paul Bakker23986e52011-04-24 08:57:21 +00001056 int ret;
1057 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001058 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +00001059
1060 if( X == B )
1061 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001062 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001063 }
1064
1065 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001066 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001067
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001068 /*
1069 * X should always be positive as a result of unsigned additions.
1070 */
1071 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001072
Paul Bakker23986e52011-04-24 08:57:21 +00001073 for( j = B->n; j > 0; j-- )
1074 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001075 break;
1076
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001077 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001078
1079 o = B->p; p = X->p; c = 0;
1080
Janos Follath6c922682015-10-30 17:43:11 +01001081 /*
1082 * tmp is used because it might happen that p == o
1083 */
Paul Bakker23986e52011-04-24 08:57:21 +00001084 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001085 {
Janos Follath6c922682015-10-30 17:43:11 +01001086 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001087 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001088 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001089 }
1090
1091 while( c != 0 )
1092 {
1093 if( i >= X->n )
1094 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001095 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001096 p = X->p + i;
1097 }
1098
Paul Bakker2d319fd2012-09-16 21:34:26 +00001099 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001100 }
1101
1102cleanup:
1103
1104 return( ret );
1105}
1106
1107/*
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001108 * Helper for mbedtls_mpi subtraction.
1109 *
1110 * Calculate d - s where d and s have the same size.
1111 * This function operates modulo (2^ciL)^n and returns the carry
1112 * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise).
1113 *
1114 * \param n Number of limbs of \p d and \p s.
1115 * \param[in,out] d On input, the left operand.
1116 * On output, the result of the subtraction:
1117 * \param[s] The right operand.
1118 *
1119 * \return 1 if `d < s`.
1120 * 0 if `d >= s`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001121 */
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001122static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1123 mbedtls_mpi_uint *d,
1124 const mbedtls_mpi_uint *s )
Paul Bakker5121ce52009-01-03 21:22:43 +00001125{
Paul Bakker23986e52011-04-24 08:57:21 +00001126 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001127 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001128
1129 for( i = c = 0; i < n; i++, s++, d++ )
1130 {
1131 z = ( *d < c ); *d -= c;
1132 c = ( *d < *s ) + z; *d -= *s;
1133 }
1134
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001135 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001136}
1137
1138/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001139 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001140 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001141int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001142{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001143 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001144 int ret;
1145 size_t n;
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001146 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001147
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001148 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1149 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001150
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001151 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001152
1153 if( X == B )
1154 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001155 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001156 B = &TB;
1157 }
1158
1159 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001160 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001161
Paul Bakker1ef7a532009-06-20 10:50:55 +00001162 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001163 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001164 */
1165 X->s = 1;
1166
Paul Bakker5121ce52009-01-03 21:22:43 +00001167 ret = 0;
1168
Paul Bakker23986e52011-04-24 08:57:21 +00001169 for( n = B->n; n > 0; n-- )
1170 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001171 break;
1172
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001173 c = mpi_sub_hlp( n, X->p, B->p );
1174 while( c != 0 )
1175 {
1176 z = ( X->p[n] < c ); X->p[n] -= c;
1177 c = z; n++;
1178 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001179
1180cleanup:
1181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001182 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001183
1184 return( ret );
1185}
1186
1187/*
1188 * Signed addition: X = A + B
1189 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001190int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001191{
1192 int ret, s = A->s;
1193
1194 if( A->s * B->s < 0 )
1195 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001196 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001197 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001198 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001199 X->s = s;
1200 }
1201 else
1202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001203 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001204 X->s = -s;
1205 }
1206 }
1207 else
1208 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001209 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001210 X->s = s;
1211 }
1212
1213cleanup:
1214
1215 return( ret );
1216}
1217
1218/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001219 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001220 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001221int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001222{
1223 int ret, s = A->s;
1224
1225 if( A->s * B->s > 0 )
1226 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001227 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001228 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001229 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001230 X->s = s;
1231 }
1232 else
1233 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001234 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001235 X->s = -s;
1236 }
1237 }
1238 else
1239 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001240 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001241 X->s = s;
1242 }
1243
1244cleanup:
1245
1246 return( ret );
1247}
1248
1249/*
1250 * Signed addition: X = A + b
1251 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001252int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001253{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001254 mbedtls_mpi _B;
1255 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001256
1257 p[0] = ( b < 0 ) ? -b : b;
1258 _B.s = ( b < 0 ) ? -1 : 1;
1259 _B.n = 1;
1260 _B.p = p;
1261
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001262 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001263}
1264
1265/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001266 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001267 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001268int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001269{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001270 mbedtls_mpi _B;
1271 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001272
1273 p[0] = ( b < 0 ) ? -b : b;
1274 _B.s = ( b < 0 ) ? -1 : 1;
1275 _B.n = 1;
1276 _B.p = p;
1277
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001278 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001279}
1280
1281/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001282 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001283 */
1284static
1285#if defined(__APPLE__) && defined(__arm__)
1286/*
1287 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1288 * appears to need this to prevent bad ARM code generation at -O3.
1289 */
1290__attribute__ ((noinline))
1291#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001292void 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 +00001293{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001294 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001295
1296#if defined(MULADDC_HUIT)
1297 for( ; i >= 8; i -= 8 )
1298 {
1299 MULADDC_INIT
1300 MULADDC_HUIT
1301 MULADDC_STOP
1302 }
1303
1304 for( ; i > 0; i-- )
1305 {
1306 MULADDC_INIT
1307 MULADDC_CORE
1308 MULADDC_STOP
1309 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001310#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001311 for( ; i >= 16; i -= 16 )
1312 {
1313 MULADDC_INIT
1314 MULADDC_CORE MULADDC_CORE
1315 MULADDC_CORE MULADDC_CORE
1316 MULADDC_CORE MULADDC_CORE
1317 MULADDC_CORE MULADDC_CORE
1318
1319 MULADDC_CORE MULADDC_CORE
1320 MULADDC_CORE MULADDC_CORE
1321 MULADDC_CORE MULADDC_CORE
1322 MULADDC_CORE MULADDC_CORE
1323 MULADDC_STOP
1324 }
1325
1326 for( ; i >= 8; i -= 8 )
1327 {
1328 MULADDC_INIT
1329 MULADDC_CORE MULADDC_CORE
1330 MULADDC_CORE MULADDC_CORE
1331
1332 MULADDC_CORE MULADDC_CORE
1333 MULADDC_CORE MULADDC_CORE
1334 MULADDC_STOP
1335 }
1336
1337 for( ; i > 0; i-- )
1338 {
1339 MULADDC_INIT
1340 MULADDC_CORE
1341 MULADDC_STOP
1342 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001343#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001344
1345 t++;
1346
1347 do {
1348 *d += c; c = ( *d < c ); d++;
1349 }
1350 while( c != 0 );
1351}
1352
1353/*
1354 * Baseline multiplication: X = A * B (HAC 14.12)
1355 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001356int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001357{
Paul Bakker23986e52011-04-24 08:57:21 +00001358 int ret;
1359 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001360 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001361
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001362 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001363
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001364 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1365 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001366
Paul Bakker23986e52011-04-24 08:57:21 +00001367 for( i = A->n; i > 0; i-- )
1368 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001369 break;
1370
Paul Bakker23986e52011-04-24 08:57:21 +00001371 for( j = B->n; j > 0; j-- )
1372 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001373 break;
1374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001375 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1376 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001377
Paul Bakker23986e52011-04-24 08:57:21 +00001378 for( i++; j > 0; j-- )
1379 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001380
1381 X->s = A->s * B->s;
1382
1383cleanup:
1384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001385 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001386
1387 return( ret );
1388}
1389
1390/*
1391 * Baseline multiplication: X = A * b
1392 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001393int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001394{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001395 mbedtls_mpi _B;
1396 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001397
1398 _B.s = 1;
1399 _B.n = 1;
1400 _B.p = p;
1401 p[0] = b;
1402
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001404}
1405
1406/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001407 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1408 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001409 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001410static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1411 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001412{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001413#if defined(MBEDTLS_HAVE_UDBL)
1414 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001415#else
Simon Butcher9803d072016-01-03 00:24:34 +00001416 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1417 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001418 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1419 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001420 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001421#endif
1422
Simon Butcher15b15d12015-11-26 19:35:03 +00001423 /*
1424 * Check for overflow
1425 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001426 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001427 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001428 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001429
Simon Butcherf5ba0452015-12-27 23:01:55 +00001430 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001431 }
1432
1433#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001434 dividend = (mbedtls_t_udbl) u1 << biL;
1435 dividend |= (mbedtls_t_udbl) u0;
1436 quotient = dividend / d;
1437 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1438 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1439
1440 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001441 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001442
1443 return (mbedtls_mpi_uint) quotient;
1444#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001445
1446 /*
1447 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1448 * Vol. 2 - Seminumerical Algorithms, Knuth
1449 */
1450
1451 /*
1452 * Normalize the divisor, d, and dividend, u0, u1
1453 */
1454 s = mbedtls_clz( d );
1455 d = d << s;
1456
1457 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001458 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001459 u0 = u0 << s;
1460
1461 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001462 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001463
1464 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001465 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001466
1467 /*
1468 * Find the first quotient and remainder
1469 */
1470 q1 = u1 / d1;
1471 r0 = u1 - d1 * q1;
1472
1473 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1474 {
1475 q1 -= 1;
1476 r0 += d1;
1477
1478 if ( r0 >= radix ) break;
1479 }
1480
Simon Butcherf5ba0452015-12-27 23:01:55 +00001481 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001482 q0 = rAX / d1;
1483 r0 = rAX - q0 * d1;
1484
1485 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1486 {
1487 q0 -= 1;
1488 r0 += d1;
1489
1490 if ( r0 >= radix ) break;
1491 }
1492
1493 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001494 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001495
1496 quotient = q1 * radix + q0;
1497
1498 return quotient;
1499#endif
1500}
1501
1502/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001503 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001504 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001505int 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 +00001506{
Paul Bakker23986e52011-04-24 08:57:21 +00001507 int ret;
1508 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001509 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1512 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001514 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1515 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001516
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001517 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001518 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001519 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1520 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001521 return( 0 );
1522 }
1523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001524 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1525 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001526 X.s = Y.s = 1;
1527
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001528 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1529 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1530 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1531 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001532
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001533 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001534 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001535 {
1536 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001537 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1538 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001539 }
1540 else k = 0;
1541
1542 n = X.n - 1;
1543 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001544 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001545
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001546 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001547 {
1548 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001549 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001550 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001551 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001552
1553 for( i = n; i > t ; i-- )
1554 {
1555 if( X.p[i] >= Y.p[t] )
1556 Z.p[i - t - 1] = ~0;
1557 else
1558 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001559 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1560 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001561 }
1562
1563 Z.p[i - t - 1]++;
1564 do
1565 {
1566 Z.p[i - t - 1]--;
1567
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001568 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001569 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001570 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001571 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001572
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001573 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001574 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1575 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001576 T2.p[2] = X.p[i];
1577 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001578 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001579
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001580 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1581 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1582 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001583
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001584 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001585 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001586 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1587 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1588 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001589 Z.p[i - t - 1]--;
1590 }
1591 }
1592
1593 if( Q != NULL )
1594 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001595 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001596 Q->s = A->s * B->s;
1597 }
1598
1599 if( R != NULL )
1600 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001601 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001602 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001603 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001604
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001605 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001606 R->s = 1;
1607 }
1608
1609cleanup:
1610
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001611 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1612 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001613
1614 return( ret );
1615}
1616
1617/*
1618 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001619 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001620int 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 +00001621{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001622 mbedtls_mpi _B;
1623 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001624
1625 p[0] = ( b < 0 ) ? -b : b;
1626 _B.s = ( b < 0 ) ? -1 : 1;
1627 _B.n = 1;
1628 _B.p = p;
1629
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001630 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001631}
1632
1633/*
1634 * Modulo: R = A mod B
1635 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001637{
1638 int ret;
1639
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001640 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1641 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001642
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001643 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001644
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001645 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1646 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001647
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001648 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1649 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001650
1651cleanup:
1652
1653 return( ret );
1654}
1655
1656/*
1657 * Modulo: r = A mod b
1658 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001659int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001660{
Paul Bakker23986e52011-04-24 08:57:21 +00001661 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001662 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001663
1664 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001665 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001666
1667 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001668 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001669
1670 /*
1671 * handle trivial cases
1672 */
1673 if( b == 1 )
1674 {
1675 *r = 0;
1676 return( 0 );
1677 }
1678
1679 if( b == 2 )
1680 {
1681 *r = A->p[0] & 1;
1682 return( 0 );
1683 }
1684
1685 /*
1686 * general case
1687 */
Paul Bakker23986e52011-04-24 08:57:21 +00001688 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001689 {
Paul Bakker23986e52011-04-24 08:57:21 +00001690 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001691 y = ( y << biH ) | ( x >> biH );
1692 z = y / b;
1693 y -= z * b;
1694
1695 x <<= biH;
1696 y = ( y << biH ) | ( x >> biH );
1697 z = y / b;
1698 y -= z * b;
1699 }
1700
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001701 /*
1702 * If A is negative, then the current y represents a negative value.
1703 * Flipping it to the positive side.
1704 */
1705 if( A->s < 0 && y != 0 )
1706 y = b - y;
1707
Paul Bakker5121ce52009-01-03 21:22:43 +00001708 *r = y;
1709
1710 return( 0 );
1711}
1712
1713/*
1714 * Fast Montgomery initialization (thanks to Tom St Denis)
1715 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001716static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001717{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001718 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001719 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001720
1721 x = m0;
1722 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001723
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001724 for( i = biL; i >= 8; i /= 2 )
1725 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001726
1727 *mm = ~x + 1;
1728}
1729
Gilles Peskined108d072020-06-04 15:00:49 +02001730/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1731 *
1732 * \param[in,out] A One of the numbers to multiply.
1733 * It must have at least one more limb than N
1734 * (A->n >= N->n + 1).
1735 * On successful completion, A contains the result of
1736 * the multiplication A * B * R^-1 mod N where
1737 * R = (2^ciL)^n.
1738 * \param[in] B One of the numbers to multiply.
1739 * It must be nonzero and must not have more limbs than N
1740 * (B->n <= N->n).
1741 * \param[in] N The modulo. N must be odd.
1742 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1743 * This is -N^-1 mod 2^ciL.
1744 * \param[in,out] T A bignum for temporary storage.
1745 * It must be at least twice the limb size of N plus 2
1746 * (T->n >= 2 * (N->n + 1)).
1747 * Its initial content is unused and
1748 * its final content is indeterminate.
1749 * Note that unlike the usual convention in the library
1750 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00001751 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001752static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001753 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001754{
Paul Bakker23986e52011-04-24 08:57:21 +00001755 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001756 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001757
1758 memset( T->p, 0, T->n * ciL );
1759
1760 d = T->p;
1761 n = N->n;
1762 m = ( B->n < n ) ? B->n : n;
1763
1764 for( i = 0; i < n; i++ )
1765 {
1766 /*
1767 * T = (T + u0*B + u1*N) / 2^biL
1768 */
1769 u0 = A->p[i];
1770 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1771
1772 mpi_mul_hlp( m, B->p, d, u0 );
1773 mpi_mul_hlp( n, N->p, d, u1 );
1774
1775 *d++ = u0; d[n + 1] = 0;
1776 }
1777
Paul Bakker66d5d072014-06-17 16:39:18 +02001778 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001779
Gilles Peskined108d072020-06-04 15:00:49 +02001780 /* If A >= N then A -= N. Do the subtraction unconditionally to prevent
Gilles Peskine7ff812e2020-06-04 21:05:24 +02001781 * timing attacks. */
1782 /* Set d to A + (2^biL)^n - N. */
1783 d[n] += 1;
Gilles Peskine6f3b68d2020-06-08 21:58:22 +02001784 d[n] -= mpi_sub_hlp( n, d, N->p );
Gilles Peskine7ff812e2020-06-04 21:05:24 +02001785 /* Now d - (2^biL)^n = A - N so d >= (2^biL)^n iff A >= N.
1786 * So we want to copy the result of the subtraction iff d->p[n] != 0.
1787 * Note that d->p[n] is either 0 or 1 since A - N <= N <= (2^biL)^n. */
Gilles Peskineea9ba772020-06-05 10:48:25 +02001788 mpi_safe_cond_assign( n + 1, A->p, d, (unsigned char) d[n] );
Gilles Peskine7ff812e2020-06-04 21:05:24 +02001789 A->p[n] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001790}
1791
1792/*
1793 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskined108d072020-06-04 15:00:49 +02001794 *
1795 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001796 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001797static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001798{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001799 mbedtls_mpi_uint z = 1;
1800 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001801
Paul Bakker8ddb6452013-02-27 14:56:33 +01001802 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001803 U.p = &z;
1804
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001805 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001806}
1807
1808/*
1809 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1810 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001811int 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 +00001812{
Paul Bakker23986e52011-04-24 08:57:21 +00001813 int ret;
1814 size_t wbits, wsize, one = 1;
1815 size_t i, j, nblimbs;
1816 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001817 mbedtls_mpi_uint ei, mm, state;
1818 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001819 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001820
Hanno Becker930ec7d2018-03-09 10:48:00 +00001821 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001822 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001823
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1825 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001826
1827 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001828 * Init temps and window size
1829 */
1830 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001831 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1832 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001833 memset( W, 0, sizeof( W ) );
1834
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001835 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001836
1837 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1838 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1839
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001840#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001841 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1842 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusf5d153d2018-12-11 14:01:44 -06001843#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001844
Paul Bakker5121ce52009-01-03 21:22:43 +00001845 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001846 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1847 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1848 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001849
1850 /*
Paul Bakker50546922012-05-19 08:40:49 +00001851 * Compensate for negative A (and correct at the end)
1852 */
1853 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001854 if( neg )
1855 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001856 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001857 Apos.s = 1;
1858 A = &Apos;
1859 }
1860
1861 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001862 * If 1st call, pre-compute R^2 mod N
1863 */
1864 if( _RR == NULL || _RR->p == NULL )
1865 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001866 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1867 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1868 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001869
1870 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001871 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001872 }
1873 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001874 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001875
1876 /*
1877 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1878 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1880 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001881 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001883
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001884 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001885
1886 /*
1887 * X = R^2 * R^-1 mod N = R mod N
1888 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001889 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001890 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001891
1892 if( wsize > 1 )
1893 {
1894 /*
1895 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1896 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001897 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001898
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001899 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1900 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001901
1902 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001903 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001904
Paul Bakker5121ce52009-01-03 21:22:43 +00001905 /*
1906 * W[i] = W[i - 1] * W[1]
1907 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001908 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001909 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001910 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1911 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001912
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001913 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001914 }
1915 }
1916
1917 nblimbs = E->n;
1918 bufsize = 0;
1919 nbits = 0;
1920 wbits = 0;
1921 state = 0;
1922
1923 while( 1 )
1924 {
1925 if( bufsize == 0 )
1926 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001927 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001928 break;
1929
Paul Bakker0d7702c2013-10-29 16:18:35 +01001930 nblimbs--;
1931
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001932 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001933 }
1934
1935 bufsize--;
1936
1937 ei = (E->p[nblimbs] >> bufsize) & 1;
1938
1939 /*
1940 * skip leading 0s
1941 */
1942 if( ei == 0 && state == 0 )
1943 continue;
1944
1945 if( ei == 0 && state == 1 )
1946 {
1947 /*
1948 * out of window, square X
1949 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001950 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001951 continue;
1952 }
1953
1954 /*
1955 * add ei to current window
1956 */
1957 state = 2;
1958
1959 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001960 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001961
1962 if( nbits == wsize )
1963 {
1964 /*
1965 * X = X^wsize R^-1 mod N
1966 */
1967 for( i = 0; i < wsize; i++ )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001968 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
1970 /*
1971 * X = X * W[wbits] R^-1 mod N
1972 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001973 mpi_montmul( X, &W[wbits], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001974
1975 state--;
1976 nbits = 0;
1977 wbits = 0;
1978 }
1979 }
1980
1981 /*
1982 * process the remaining bits
1983 */
1984 for( i = 0; i < nbits; i++ )
1985 {
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001986 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001987
1988 wbits <<= 1;
1989
Paul Bakker66d5d072014-06-17 16:39:18 +02001990 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001991 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001992 }
1993
1994 /*
1995 * X = A^E * R * R^-1 mod N = A^E mod N
1996 */
Gilles Peskine8ff7cc92020-06-04 20:55:15 +02001997 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001998
Hanno Beckera4af1c42017-04-18 09:07:45 +01001999 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002000 {
2001 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002002 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002003 }
2004
Paul Bakker5121ce52009-01-03 21:22:43 +00002005cleanup:
2006
Paul Bakker66d5d072014-06-17 16:39:18 +02002007 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002008 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002009
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002010 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002011
Paul Bakker75a28602014-03-31 12:08:17 +02002012 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002013 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002014
2015 return( ret );
2016}
2017
Paul Bakker5121ce52009-01-03 21:22:43 +00002018/*
2019 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2020 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002021int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002022{
Paul Bakker23986e52011-04-24 08:57:21 +00002023 int ret;
2024 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002025 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002026
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002027 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002028
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2030 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002032 lz = mbedtls_mpi_lsb( &TA );
2033 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002034
Paul Bakker66d5d072014-06-17 16:39:18 +02002035 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002036 lz = lzt;
2037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002038 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2039 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002040
Paul Bakker5121ce52009-01-03 21:22:43 +00002041 TA.s = TB.s = 1;
2042
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002043 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002044 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002045 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2046 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002047
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002048 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002049 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002050 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2051 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002052 }
2053 else
2054 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002055 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2056 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002057 }
2058 }
2059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2061 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002062
2063cleanup:
2064
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002065 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002066
2067 return( ret );
2068}
2069
Paul Bakker33dc46b2014-04-30 16:11:39 +02002070/*
2071 * Fill X with size bytes of random.
2072 *
2073 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002074 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002075 * deterministic, eg for tests).
2076 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002077int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002078 int (*f_rng)(void *, unsigned char *, size_t),
2079 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002080{
Paul Bakker23986e52011-04-24 08:57:21 +00002081 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002082 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02002083
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002084 if( size > MBEDTLS_MPI_MAX_SIZE )
2085 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002086
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002087 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2088 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002089
2090cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01002091 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002092 return( ret );
2093}
2094
Paul Bakker5121ce52009-01-03 21:22:43 +00002095/*
2096 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2097 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002098int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002099{
2100 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002101 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002102
Hanno Becker4bcb4912017-04-18 15:49:39 +01002103 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002104 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002105
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002106 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2107 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2108 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002110 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002111
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002112 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002113 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002114 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002115 goto cleanup;
2116 }
2117
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002118 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2119 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2120 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2121 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002123 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2124 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2125 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2126 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002127
2128 do
2129 {
2130 while( ( TU.p[0] & 1 ) == 0 )
2131 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002132 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002133
2134 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2135 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002136 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2137 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002138 }
2139
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002140 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2141 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002142 }
2143
2144 while( ( TV.p[0] & 1 ) == 0 )
2145 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002146 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002147
2148 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2149 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002150 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2151 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002152 }
2153
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002154 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2155 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002156 }
2157
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002158 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002159 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2161 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2162 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002163 }
2164 else
2165 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002166 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2167 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2168 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002169 }
2170 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002171 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002172
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002173 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2174 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002175
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002176 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2177 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002178
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002179 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002180
2181cleanup:
2182
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002183 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2184 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2185 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002186
2187 return( ret );
2188}
2189
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002190#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002191
Paul Bakker5121ce52009-01-03 21:22:43 +00002192static const int small_prime[] =
2193{
2194 3, 5, 7, 11, 13, 17, 19, 23,
2195 29, 31, 37, 41, 43, 47, 53, 59,
2196 61, 67, 71, 73, 79, 83, 89, 97,
2197 101, 103, 107, 109, 113, 127, 131, 137,
2198 139, 149, 151, 157, 163, 167, 173, 179,
2199 181, 191, 193, 197, 199, 211, 223, 227,
2200 229, 233, 239, 241, 251, 257, 263, 269,
2201 271, 277, 281, 283, 293, 307, 311, 313,
2202 317, 331, 337, 347, 349, 353, 359, 367,
2203 373, 379, 383, 389, 397, 401, 409, 419,
2204 421, 431, 433, 439, 443, 449, 457, 461,
2205 463, 467, 479, 487, 491, 499, 503, 509,
2206 521, 523, 541, 547, 557, 563, 569, 571,
2207 577, 587, 593, 599, 601, 607, 613, 617,
2208 619, 631, 641, 643, 647, 653, 659, 661,
2209 673, 677, 683, 691, 701, 709, 719, 727,
2210 733, 739, 743, 751, 757, 761, 769, 773,
2211 787, 797, 809, 811, 821, 823, 827, 829,
2212 839, 853, 857, 859, 863, 877, 881, 883,
2213 887, 907, 911, 919, 929, 937, 941, 947,
2214 953, 967, 971, 977, 983, 991, 997, -103
2215};
2216
2217/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002218 * Small divisors test (X must be positive)
2219 *
2220 * Return values:
2221 * 0: no small factor (possible prime, more tests needed)
2222 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002223 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002224 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002225 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002226static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002227{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002228 int ret = 0;
2229 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002230 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002231
Paul Bakker5121ce52009-01-03 21:22:43 +00002232 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002233 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002234
2235 for( i = 0; small_prime[i] > 0; i++ )
2236 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002237 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002238 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002239
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002240 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002241
2242 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002243 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002244 }
2245
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002246cleanup:
2247 return( ret );
2248}
2249
2250/*
2251 * Miller-Rabin pseudo-primality test (HAC 4.24)
2252 */
Janos Follath72d555d2018-09-03 14:45:23 +01002253static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002254 int (*f_rng)(void *, unsigned char *, size_t),
2255 void *p_rng )
2256{
Pascal Junodb99183d2015-03-11 16:49:45 +01002257 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002258 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002259 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002260
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002261 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2262 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002263
Paul Bakker5121ce52009-01-03 21:22:43 +00002264 /*
2265 * W = |X| - 1
2266 * R = W >> lsb( W )
2267 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002268 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2269 s = mbedtls_mpi_lsb( &W );
2270 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2271 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002272
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002273 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002274
Janos Follath72d555d2018-09-03 14:45:23 +01002275 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002276 {
2277 /*
2278 * pick a random A, 1 < A < |X| - 1
2279 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002280 count = 0;
2281 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002282 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002283
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002284 j = mbedtls_mpi_bitlen( &A );
2285 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002286 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002287 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002288 }
2289
2290 if (count++ > 30) {
Jens Wiklanderb2aa9382019-01-17 13:30:57 +01002291 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2292 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002293 }
2294
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002295 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2296 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002297
2298 /*
2299 * A = A^R mod |X|
2300 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002301 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002302
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002303 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2304 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002305 continue;
2306
2307 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002308 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002309 {
2310 /*
2311 * A = A * A mod |X|
2312 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002313 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2314 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002315
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002316 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002317 break;
2318
2319 j++;
2320 }
2321
2322 /*
2323 * not prime if A != |X| - 1 or A == 1
2324 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002325 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2326 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002327 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002328 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002329 break;
2330 }
2331 }
2332
2333cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002334 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2335 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002336
2337 return( ret );
2338}
2339
2340/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002341 * Pseudo-primality test: small factors, then Miller-Rabin
2342 */
Darryl Green94759f62018-10-16 15:09:19 +01002343static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002344 int (*f_rng)(void *, unsigned char *, size_t),
2345 void *p_rng )
2346{
2347 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002348 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002349
2350 XX.s = 1;
2351 XX.n = X->n;
2352 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002354 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2355 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2356 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002358 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002359 return( 0 );
2360
2361 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2362 {
2363 if( ret == 1 )
2364 return( 0 );
2365
2366 return( ret );
2367 }
2368
Janos Follath72d555d2018-09-03 14:45:23 +01002369 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2370}
2371
2372/*
2373 * Pseudo-primality test, error probability 2^-80
2374 */
2375int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2376 int (*f_rng)(void *, unsigned char *, size_t),
2377 void *p_rng )
2378{
2379 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002380}
2381
2382/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002383 * Prime number generation
2384 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002386 int (*f_rng)(void *, unsigned char *, size_t),
2387 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002388{
Paul Bakker23986e52011-04-24 08:57:21 +00002389 int ret;
2390 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002391 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002392 mbedtls_mpi_uint r;
2393 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002394
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002395 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2396 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002397
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002398 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002399
2400 n = BITS_TO_LIMBS( nbits );
2401
Janos Follath72d555d2018-09-03 14:45:23 +01002402 /*
2403 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2404 */
2405 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2406 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2407 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002409 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002410
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002411 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002412 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002413
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002414 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002415
2416 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002417
2418 if( dh_flag == 0 )
2419 {
Janos Follath72d555d2018-09-03 14:45:23 +01002420 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002421 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002422 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002423 goto cleanup;
2424
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002425 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002426 }
2427 }
2428 else
2429 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002430 /*
2431 * An necessary condition for Y and X = 2Y + 1 to be prime
2432 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2433 * Make sure it is satisfied, while keeping X = 3 mod 4
2434 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002435
2436 X->p[0] |= 2;
2437
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002438 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002439 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002441 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002442 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002443
2444 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002445 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2446 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002447
2448 while( 1 )
2449 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002450 /*
2451 * First, check small factors for X and Y
2452 * before doing Miller-Rabin on any of them
2453 */
2454 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2455 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002456 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2457 == 0 &&
2458 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2459 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002460 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002461 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002462 }
2463
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002464 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002465 goto cleanup;
2466
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002467 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002468 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002469 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2470 * so up Y by 6 and X by 12.
2471 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002472 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2473 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002474 }
2475 }
2476
2477cleanup:
2478
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002479 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002480
2481 return( ret );
2482}
2483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002484#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002485
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002486#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002487
Paul Bakker23986e52011-04-24 08:57:21 +00002488#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002489
2490static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2491{
2492 { 693, 609, 21 },
2493 { 1764, 868, 28 },
2494 { 768454923, 542167814, 1 }
2495};
2496
Paul Bakker5121ce52009-01-03 21:22:43 +00002497/*
2498 * Checkup routine
2499 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002500int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002501{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002502 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002503 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002504
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002505 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2506 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002508 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002509 "EFE021C2645FD1DC586E69184AF4A31E" \
2510 "D5F53E93B5F123FA41680867BA110131" \
2511 "944FE7952E2517337780CB0DB80E61AA" \
2512 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002514 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002515 "B2E7EFD37075B9F03FF989C7C5051C20" \
2516 "34D2A323810251127E7BF8625A4F49A5" \
2517 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2518 "5B5C25763222FEFCCFC38B832366C29E" ) );
2519
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002520 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002521 "0066A198186C18C10B2F5ED9B522752A" \
2522 "9830B69916E535C8F047518A889A43A5" \
2523 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002525 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002526
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002527 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002528 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2529 "9E857EA95A03512E2BAE7391688D264A" \
2530 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2531 "8001B72E848A38CAE1C65F78E56ABDEF" \
2532 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2533 "ECF677152EF804370C1A305CAF3B5BF1" \
2534 "30879B56C61DE584A0F53A2447A51E" ) );
2535
2536 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002537 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002538
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002539 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002540 {
2541 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002542 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002543
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002544 ret = 1;
2545 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002546 }
2547
2548 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002549 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002550
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002551 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002552
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002553 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002554 "256567336059E52CAE22925474705F39A94" ) );
2555
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002556 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002557 "6613F26162223DF488E9CD48CC132C7A" \
2558 "0AC93C701B001B092E4E5B9F73BCD27B" \
2559 "9EE50D0657C77F374E903CDFA4C642" ) );
2560
2561 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002563
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002564 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2565 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002566 {
2567 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002568 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002569
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002570 ret = 1;
2571 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002572 }
2573
2574 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002575 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002576
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002577 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002578
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002579 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002580 "36E139AEA55215609D2816998ED020BB" \
2581 "BD96C37890F65171D948E9BC7CBAA4D9" \
2582 "325D24D6A3C12710F10A09FA08AB87" ) );
2583
2584 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002585 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002586
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002587 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002588 {
2589 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002590 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002591
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002592 ret = 1;
2593 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002594 }
2595
2596 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002597 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002598
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002599 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002600
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002601 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002602 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2603 "C3DBA76456363A10869622EAC2DD84EC" \
2604 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2605
2606 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002607 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002608
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002609 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002610 {
2611 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002612 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002613
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002614 ret = 1;
2615 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002616 }
2617
2618 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002619 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002620
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002621 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002622 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002623
Paul Bakker66d5d072014-06-17 16:39:18 +02002624 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002625 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002626 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2627 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002628
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002629 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002630
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002631 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002632 {
2633 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002634 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002635
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002636 ret = 1;
2637 goto cleanup;
2638 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002639 }
2640
2641 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002642 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002643
Paul Bakker5121ce52009-01-03 21:22:43 +00002644cleanup:
2645
2646 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002647 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002648
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002649 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2650 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002651
2652 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002653 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002654
2655 return( ret );
2656}
2657
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002658#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002659
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002660#endif /* MBEDTLS_BIGNUM_C */