blob: 4ab97b912770b4dbf78e69202c658d8113f20280 [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
154 /* Actually resize up in this case */
155 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100157
158 for( i = X->n - 1; i > 0; i-- )
159 if( X->p[i] != 0 )
160 break;
161 i++;
162
163 if( i < nblimbs )
164 i = nblimbs;
165
Simon Butcher29176892016-05-20 00:19:09 +0100166 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200167 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100168
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100169 if( X->p != NULL )
170 {
171 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200172 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100174 }
175
176 X->n = i;
177 X->p = p;
178
179 return( 0 );
180}
181
182/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000183 * Copy the contents of Y into X
184 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000186{
Paul Bakker23986e52011-04-24 08:57:21 +0000187 int ret;
188 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000189
190 if( X == Y )
191 return( 0 );
192
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200193 if( Y->p == NULL )
194 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200195 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200196 return( 0 );
197 }
198
Paul Bakker5121ce52009-01-03 21:22:43 +0000199 for( i = Y->n - 1; i > 0; i-- )
200 if( Y->p[i] != 0 )
201 break;
202 i++;
203
204 X->s = Y->s;
205
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000207
208 memset( X->p, 0, X->n * ciL );
209 memcpy( X->p, Y->p, i * ciL );
210
211cleanup:
212
213 return( ret );
214}
215
216/*
217 * Swap the contents of X and Y
218 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000220{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200223 memcpy( &T, X, sizeof( mbedtls_mpi ) );
224 memcpy( X, Y, sizeof( mbedtls_mpi ) );
225 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000226}
227
228/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100229 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100230 * about whether the assignment was made or not.
231 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100234{
235 int ret = 0;
236 size_t i;
237
Pascal Junodb99183d2015-03-11 16:49:45 +0100238 /* make sure assign is 0 or 1 in a time-constant manner */
239 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100242
Paul Bakker66d5d072014-06-17 16:39:18 +0200243 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100244
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100245 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200246 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100247
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100248 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200249 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250
251cleanup:
252 return( ret );
253}
254
255/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100256 * Conditionally swap X and Y, without leaking information
257 * about whether the swap was made or not.
258 * Here it is not ok to simply swap the pointers, which whould lead to
259 * different memory access patterns when X and Y are used afterwards.
260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100262{
263 int ret, s;
264 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100266
267 if( X == Y )
268 return( 0 );
269
Pascal Junodb99183d2015-03-11 16:49:45 +0100270 /* make sure swap is 0 or 1 in a time-constant manner */
271 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100272
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200273 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
274 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100275
276 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200277 X->s = X->s * ( 1 - swap ) + Y->s * swap;
278 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100279
280
281 for( i = 0; i < X->n; i++ )
282 {
283 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200284 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
285 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286 }
287
288cleanup:
289 return( ret );
290}
291
292/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000293 * Set value from integer
294 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200295int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000296{
297 int ret;
298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000300 memset( X->p, 0, X->n * ciL );
301
302 X->p[0] = ( z < 0 ) ? -z : z;
303 X->s = ( z < 0 ) ? -1 : 1;
304
305cleanup:
306
307 return( ret );
308}
309
310/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000311 * Get a specific bit
312 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200313int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000314{
315 if( X->n * biL <= pos )
316 return( 0 );
317
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200318 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000319}
320
321/*
322 * Set a bit to a specific value of 0 or 1
323 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200324int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000325{
326 int ret = 0;
327 size_t off = pos / biL;
328 size_t idx = pos % biL;
329
330 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200331 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200332
Paul Bakker2f5947e2011-05-18 15:47:11 +0000333 if( X->n * biL <= pos )
334 {
335 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200336 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200338 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000339 }
340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
342 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000343
344cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200345
Paul Bakker2f5947e2011-05-18 15:47:11 +0000346 return( ret );
347}
348
349/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200350 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000351 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200352size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000353{
Paul Bakker23986e52011-04-24 08:57:21 +0000354 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000355
356 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000357 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000358 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
359 return( count );
360
361 return( 0 );
362}
363
364/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000365 * Count leading zero bits in a given integer
366 */
367static size_t mbedtls_clz( const mbedtls_mpi_uint x )
368{
369 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100370 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000371
372 for( j = 0; j < biL; j++ )
373 {
374 if( x & mask ) break;
375
376 mask >>= 1;
377 }
378
379 return j;
380}
381
382/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200383 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000384 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200385size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000386{
Paul Bakker23986e52011-04-24 08:57:21 +0000387 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000388
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200389 if( X->n == 0 )
390 return( 0 );
391
Paul Bakker5121ce52009-01-03 21:22:43 +0000392 for( i = X->n - 1; i > 0; i-- )
393 if( X->p[i] != 0 )
394 break;
395
Simon Butcher15b15d12015-11-26 19:35:03 +0000396 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000397
Paul Bakker23986e52011-04-24 08:57:21 +0000398 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000399}
400
401/*
402 * Return the total size in bytes
403 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200404size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000405{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200406 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000407}
408
409/*
410 * Convert an ASCII character to digit value
411 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200412static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000413{
414 *d = 255;
415
416 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
417 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
418 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
419
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200420 if( *d >= (mbedtls_mpi_uint) radix )
421 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000422
423 return( 0 );
424}
425
426/*
427 * Import from an ASCII string
428 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200429int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000430{
Paul Bakker23986e52011-04-24 08:57:21 +0000431 int ret;
432 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433 mbedtls_mpi_uint d;
434 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000435
436 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000438
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200439 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000440
Paul Bakkerff60ee62010-03-16 21:09:09 +0000441 slen = strlen( s );
442
Paul Bakker5121ce52009-01-03 21:22:43 +0000443 if( radix == 16 )
444 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100445 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200446 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
447
Paul Bakkerff60ee62010-03-16 21:09:09 +0000448 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000449
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200450 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
451 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000452
Paul Bakker23986e52011-04-24 08:57:21 +0000453 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000454 {
Paul Bakker23986e52011-04-24 08:57:21 +0000455 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000456 {
457 X->s = -1;
458 break;
459 }
460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200461 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200462 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000463 }
464 }
465 else
466 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000468
Paul Bakkerff60ee62010-03-16 21:09:09 +0000469 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000470 {
471 if( i == 0 && s[i] == '-' )
472 {
473 X->s = -1;
474 continue;
475 }
476
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
478 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000479
480 if( X->s == 1 )
481 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000483 }
484 else
485 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000487 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000488 }
489 }
490
491cleanup:
492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494
495 return( ret );
496}
497
498/*
Ron Eldore6cbfc32018-11-20 14:07:01 +0200499 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000500 */
Ron Eldore6cbfc32018-11-20 14:07:01 +0200501static int mpi_write_hlp( mbedtls_mpi *X, int radix,
502 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000503{
504 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200505 mbedtls_mpi_uint r;
Ron Eldore6cbfc32018-11-20 14:07:01 +0200506 size_t length = 0;
507 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000508
Ron Eldore6cbfc32018-11-20 14:07:01 +0200509 do
510 {
511 if( length >= buflen )
512 {
513 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
514 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000515
Ron Eldore6cbfc32018-11-20 14:07:01 +0200516 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
517 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
518 /*
519 * Write the residue in the current position, as an ASCII character.
520 */
521 if( r < 0xA )
522 *(--p_end) = (char)( '0' + r );
523 else
524 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000525
Ron Eldore6cbfc32018-11-20 14:07:01 +0200526 length++;
527 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000528
Ron Eldore6cbfc32018-11-20 14:07:01 +0200529 memmove( *p, p_end, length );
530 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000531
532cleanup:
533
534 return( ret );
535}
536
537/*
538 * Export into an ASCII string
539 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100540int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
541 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000542{
Paul Bakker23986e52011-04-24 08:57:21 +0000543 int ret = 0;
544 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000545 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000547
548 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200549 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000550
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200551 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000552 if( radix >= 4 ) n >>= 1;
553 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000554 /*
555 * Round up the buffer length to an even value to ensure that there is
556 * enough room for hexadecimal values that can be represented in an odd
557 * number of digits.
558 */
559 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000560
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100561 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000562 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100563 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200564 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000565 }
566
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100567 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200568 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000569
570 if( X->s == -1 )
571 *p++ = '-';
572
573 if( radix == 16 )
574 {
Paul Bakker23986e52011-04-24 08:57:21 +0000575 int c;
576 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000577
Paul Bakker23986e52011-04-24 08:57:21 +0000578 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000579 {
Paul Bakker23986e52011-04-24 08:57:21 +0000580 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000581 {
Paul Bakker23986e52011-04-24 08:57:21 +0000582 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000583
Paul Bakker6c343d72014-07-10 14:36:19 +0200584 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000585 continue;
586
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000587 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000588 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000589 k = 1;
590 }
591 }
592 }
593 else
594 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200595 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000596
597 if( T.s == -1 )
598 T.s = 1;
599
Ron Eldore6cbfc32018-11-20 14:07:01 +0200600 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000601 }
602
603 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100604 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000605
606cleanup:
607
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000609
610 return( ret );
611}
612
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000614/*
615 * Read X from an opened file
616 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000618{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200619 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000620 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000621 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000622 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000623 * Buffer should have space for (short) label and decimal formatted MPI,
624 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000625 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200626 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000627
628 memset( s, 0, sizeof( s ) );
629 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000631
632 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000633 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200634 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000635
Hanno Beckerb2034b72017-04-26 11:46:46 +0100636 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
637 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000638
639 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100640 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000641 if( mpi_get_digit( &d, radix, *p ) != 0 )
642 break;
643
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200644 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000645}
646
647/*
648 * Write X into an opened file (or stdout if fout == NULL)
649 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000651{
Paul Bakker23986e52011-04-24 08:57:21 +0000652 int ret;
653 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000654 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000655 * Buffer should have space for (short) label and decimal formatted MPI,
656 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000657 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000659
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100660 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000661
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100662 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000663
664 if( p == NULL ) p = "";
665
666 plen = strlen( p );
667 slen = strlen( s );
668 s[slen++] = '\r';
669 s[slen++] = '\n';
670
671 if( fout != NULL )
672 {
673 if( fwrite( p, 1, plen, fout ) != plen ||
674 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200675 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000676 }
677 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000679
680cleanup:
681
682 return( ret );
683}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000685
686/*
687 * Import X from unsigned binary data, big endian
688 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000690{
Paul Bakker23986e52011-04-24 08:57:21 +0000691 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100692 size_t i, j;
693 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000694
Hanno Becker073c1992017-10-17 15:17:27 +0100695 /* Ensure that target MPI has exactly the necessary number of limbs */
696 if( X->n != limbs )
697 {
698 mbedtls_mpi_free( X );
699 mbedtls_mpi_init( X );
700 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
701 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000702
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000704
Hanno Becker073c1992017-10-17 15:17:27 +0100705 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
708cleanup:
709
710 return( ret );
711}
712
713/*
714 * Export X into unsigned binary data, big endian
715 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200716int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000717{
Paul Bakker23986e52011-04-24 08:57:21 +0000718 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000719
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200720 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000721
722 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200723 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000724
725 memset( buf, 0, buflen );
726
727 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
728 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
729
730 return( 0 );
731}
732
733/*
734 * Left-shift: X <<= count
735 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200736int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000737{
Paul Bakker23986e52011-04-24 08:57:21 +0000738 int ret;
739 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200740 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000741
742 v0 = count / (biL );
743 t1 = count & (biL - 1);
744
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200745 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000746
Paul Bakkerf9688572011-05-05 10:00:45 +0000747 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200748 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000749
750 ret = 0;
751
752 /*
753 * shift by count / limb_size
754 */
755 if( v0 > 0 )
756 {
Paul Bakker23986e52011-04-24 08:57:21 +0000757 for( i = X->n; i > v0; i-- )
758 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000759
Paul Bakker23986e52011-04-24 08:57:21 +0000760 for( ; i > 0; i-- )
761 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000762 }
763
764 /*
765 * shift by count % limb_size
766 */
767 if( t1 > 0 )
768 {
769 for( i = v0; i < X->n; i++ )
770 {
771 r1 = X->p[i] >> (biL - t1);
772 X->p[i] <<= t1;
773 X->p[i] |= r0;
774 r0 = r1;
775 }
776 }
777
778cleanup:
779
780 return( ret );
781}
782
783/*
784 * Right-shift: X >>= count
785 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200786int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000787{
Paul Bakker23986e52011-04-24 08:57:21 +0000788 size_t i, v0, v1;
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 v1 = count & (biL - 1);
793
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100794 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200795 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100796
Paul Bakker5121ce52009-01-03 21:22:43 +0000797 /*
798 * shift by count / limb_size
799 */
800 if( v0 > 0 )
801 {
802 for( i = 0; i < X->n - v0; i++ )
803 X->p[i] = X->p[i + v0];
804
805 for( ; i < X->n; i++ )
806 X->p[i] = 0;
807 }
808
809 /*
810 * shift by count % limb_size
811 */
812 if( v1 > 0 )
813 {
Paul Bakker23986e52011-04-24 08:57:21 +0000814 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000815 {
Paul Bakker23986e52011-04-24 08:57:21 +0000816 r1 = X->p[i - 1] << (biL - v1);
817 X->p[i - 1] >>= v1;
818 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000819 r0 = r1;
820 }
821 }
822
823 return( 0 );
824}
825
826/*
827 * Compare unsigned values
828 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200829int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000830{
Paul Bakker23986e52011-04-24 08:57:21 +0000831 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000832
Paul Bakker23986e52011-04-24 08:57:21 +0000833 for( i = X->n; i > 0; i-- )
834 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000835 break;
836
Paul Bakker23986e52011-04-24 08:57:21 +0000837 for( j = Y->n; j > 0; j-- )
838 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000839 break;
840
Paul Bakker23986e52011-04-24 08:57:21 +0000841 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000842 return( 0 );
843
844 if( i > j ) return( 1 );
845 if( j > i ) return( -1 );
846
Paul Bakker23986e52011-04-24 08:57:21 +0000847 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000848 {
Paul Bakker23986e52011-04-24 08:57:21 +0000849 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
850 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000851 }
852
853 return( 0 );
854}
855
856/*
857 * Compare signed values
858 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200859int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000860{
Paul Bakker23986e52011-04-24 08:57:21 +0000861 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000862
Paul Bakker23986e52011-04-24 08:57:21 +0000863 for( i = X->n; i > 0; i-- )
864 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000865 break;
866
Paul Bakker23986e52011-04-24 08:57:21 +0000867 for( j = Y->n; j > 0; j-- )
868 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000869 break;
870
Paul Bakker23986e52011-04-24 08:57:21 +0000871 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000872 return( 0 );
873
874 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000875 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000876
877 if( X->s > 0 && Y->s < 0 ) return( 1 );
878 if( Y->s > 0 && X->s < 0 ) return( -1 );
879
Paul Bakker23986e52011-04-24 08:57:21 +0000880 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000881 {
Paul Bakker23986e52011-04-24 08:57:21 +0000882 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
883 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000884 }
885
886 return( 0 );
887}
888
889/*
890 * Compare signed values
891 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200892int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000893{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200894 mbedtls_mpi Y;
895 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000896
897 *p = ( z < 0 ) ? -z : z;
898 Y.s = ( z < 0 ) ? -1 : 1;
899 Y.n = 1;
900 Y.p = p;
901
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200902 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000903}
904
905/*
906 * Unsigned addition: X = |A| + |B| (HAC 14.7)
907 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200908int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000909{
Paul Bakker23986e52011-04-24 08:57:21 +0000910 int ret;
911 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100912 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000913
914 if( X == B )
915 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200916 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000917 }
918
919 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200920 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200921
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000922 /*
923 * X should always be positive as a result of unsigned additions.
924 */
925 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000926
Paul Bakker23986e52011-04-24 08:57:21 +0000927 for( j = B->n; j > 0; j-- )
928 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000929 break;
930
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200931 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000932
933 o = B->p; p = X->p; c = 0;
934
Janos Follath6c922682015-10-30 17:43:11 +0100935 /*
936 * tmp is used because it might happen that p == o
937 */
Paul Bakker23986e52011-04-24 08:57:21 +0000938 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000939 {
Janos Follath6c922682015-10-30 17:43:11 +0100940 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000941 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100942 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000943 }
944
945 while( c != 0 )
946 {
947 if( i >= X->n )
948 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200949 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000950 p = X->p + i;
951 }
952
Paul Bakker2d319fd2012-09-16 21:34:26 +0000953 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000954 }
955
956cleanup:
957
958 return( ret );
959}
960
961/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200962 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000963 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200964static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000965{
Paul Bakker23986e52011-04-24 08:57:21 +0000966 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200967 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000968
969 for( i = c = 0; i < n; i++, s++, d++ )
970 {
971 z = ( *d < c ); *d -= c;
972 c = ( *d < *s ) + z; *d -= *s;
973 }
974
975 while( c != 0 )
976 {
977 z = ( *d < c ); *d -= c;
978 c = z; i++; d++;
979 }
980}
981
982/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100983 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000984 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200985int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000986{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200987 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000988 int ret;
989 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000990
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200991 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
992 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000993
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200994 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000995
996 if( X == B )
997 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200998 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000999 B = &TB;
1000 }
1001
1002 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001003 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001004
Paul Bakker1ef7a532009-06-20 10:50:55 +00001005 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001006 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001007 */
1008 X->s = 1;
1009
Paul Bakker5121ce52009-01-03 21:22:43 +00001010 ret = 0;
1011
Paul Bakker23986e52011-04-24 08:57:21 +00001012 for( n = B->n; n > 0; n-- )
1013 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001014 break;
1015
Paul Bakker23986e52011-04-24 08:57:21 +00001016 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001017
1018cleanup:
1019
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001020 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001021
1022 return( ret );
1023}
1024
1025/*
1026 * Signed addition: X = A + B
1027 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001028int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001029{
1030 int ret, s = A->s;
1031
1032 if( A->s * B->s < 0 )
1033 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001034 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001035 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001036 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001037 X->s = s;
1038 }
1039 else
1040 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001041 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001042 X->s = -s;
1043 }
1044 }
1045 else
1046 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001047 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001048 X->s = s;
1049 }
1050
1051cleanup:
1052
1053 return( ret );
1054}
1055
1056/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001057 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001058 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001059int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001060{
1061 int ret, s = A->s;
1062
1063 if( A->s * B->s > 0 )
1064 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001065 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001066 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001067 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001068 X->s = s;
1069 }
1070 else
1071 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001072 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001073 X->s = -s;
1074 }
1075 }
1076 else
1077 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001078 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001079 X->s = s;
1080 }
1081
1082cleanup:
1083
1084 return( ret );
1085}
1086
1087/*
1088 * Signed addition: X = A + b
1089 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001090int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001091{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001092 mbedtls_mpi _B;
1093 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001094
1095 p[0] = ( b < 0 ) ? -b : b;
1096 _B.s = ( b < 0 ) ? -1 : 1;
1097 _B.n = 1;
1098 _B.p = p;
1099
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001100 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001101}
1102
1103/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001104 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001105 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001106int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001107{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001108 mbedtls_mpi _B;
1109 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001110
1111 p[0] = ( b < 0 ) ? -b : b;
1112 _B.s = ( b < 0 ) ? -1 : 1;
1113 _B.n = 1;
1114 _B.p = p;
1115
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001116 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001117}
1118
1119/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001120 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001121 */
1122static
1123#if defined(__APPLE__) && defined(__arm__)
1124/*
1125 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1126 * appears to need this to prevent bad ARM code generation at -O3.
1127 */
1128__attribute__ ((noinline))
1129#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001130void 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 +00001131{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001132 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001133
1134#if defined(MULADDC_HUIT)
1135 for( ; i >= 8; i -= 8 )
1136 {
1137 MULADDC_INIT
1138 MULADDC_HUIT
1139 MULADDC_STOP
1140 }
1141
1142 for( ; i > 0; i-- )
1143 {
1144 MULADDC_INIT
1145 MULADDC_CORE
1146 MULADDC_STOP
1147 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001148#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001149 for( ; i >= 16; i -= 16 )
1150 {
1151 MULADDC_INIT
1152 MULADDC_CORE MULADDC_CORE
1153 MULADDC_CORE MULADDC_CORE
1154 MULADDC_CORE MULADDC_CORE
1155 MULADDC_CORE MULADDC_CORE
1156
1157 MULADDC_CORE MULADDC_CORE
1158 MULADDC_CORE MULADDC_CORE
1159 MULADDC_CORE MULADDC_CORE
1160 MULADDC_CORE MULADDC_CORE
1161 MULADDC_STOP
1162 }
1163
1164 for( ; i >= 8; i -= 8 )
1165 {
1166 MULADDC_INIT
1167 MULADDC_CORE MULADDC_CORE
1168 MULADDC_CORE MULADDC_CORE
1169
1170 MULADDC_CORE MULADDC_CORE
1171 MULADDC_CORE MULADDC_CORE
1172 MULADDC_STOP
1173 }
1174
1175 for( ; i > 0; i-- )
1176 {
1177 MULADDC_INIT
1178 MULADDC_CORE
1179 MULADDC_STOP
1180 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001181#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001182
1183 t++;
1184
1185 do {
1186 *d += c; c = ( *d < c ); d++;
1187 }
1188 while( c != 0 );
1189}
1190
1191/*
1192 * Baseline multiplication: X = A * B (HAC 14.12)
1193 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001194int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001195{
Paul Bakker23986e52011-04-24 08:57:21 +00001196 int ret;
1197 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001198 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001199
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001200 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001202 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1203 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001204
Paul Bakker23986e52011-04-24 08:57:21 +00001205 for( i = A->n; i > 0; i-- )
1206 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001207 break;
1208
Paul Bakker23986e52011-04-24 08:57:21 +00001209 for( j = B->n; j > 0; j-- )
1210 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001211 break;
1212
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001213 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1214 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001215
Paul Bakker23986e52011-04-24 08:57:21 +00001216 for( i++; j > 0; j-- )
1217 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001218
1219 X->s = A->s * B->s;
1220
1221cleanup:
1222
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001223 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001224
1225 return( ret );
1226}
1227
1228/*
1229 * Baseline multiplication: X = A * b
1230 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001231int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001232{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001233 mbedtls_mpi _B;
1234 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001235
1236 _B.s = 1;
1237 _B.n = 1;
1238 _B.p = p;
1239 p[0] = b;
1240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001241 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001242}
1243
1244/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001245 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1246 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001247 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001248static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1249 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001250{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001251#if defined(MBEDTLS_HAVE_UDBL)
1252 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001253#else
Simon Butcher9803d072016-01-03 00:24:34 +00001254 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1255 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001256 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1257 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001258 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001259#endif
1260
Simon Butcher15b15d12015-11-26 19:35:03 +00001261 /*
1262 * Check for overflow
1263 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001264 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001265 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001266 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001267
Simon Butcherf5ba0452015-12-27 23:01:55 +00001268 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001269 }
1270
1271#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001272 dividend = (mbedtls_t_udbl) u1 << biL;
1273 dividend |= (mbedtls_t_udbl) u0;
1274 quotient = dividend / d;
1275 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1276 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1277
1278 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001279 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001280
1281 return (mbedtls_mpi_uint) quotient;
1282#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001283
1284 /*
1285 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1286 * Vol. 2 - Seminumerical Algorithms, Knuth
1287 */
1288
1289 /*
1290 * Normalize the divisor, d, and dividend, u0, u1
1291 */
1292 s = mbedtls_clz( d );
1293 d = d << s;
1294
1295 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001296 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001297 u0 = u0 << s;
1298
1299 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001300 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001301
1302 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001303 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001304
1305 /*
1306 * Find the first quotient and remainder
1307 */
1308 q1 = u1 / d1;
1309 r0 = u1 - d1 * q1;
1310
1311 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1312 {
1313 q1 -= 1;
1314 r0 += d1;
1315
1316 if ( r0 >= radix ) break;
1317 }
1318
Simon Butcherf5ba0452015-12-27 23:01:55 +00001319 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001320 q0 = rAX / d1;
1321 r0 = rAX - q0 * d1;
1322
1323 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1324 {
1325 q0 -= 1;
1326 r0 += d1;
1327
1328 if ( r0 >= radix ) break;
1329 }
1330
1331 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001332 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001333
1334 quotient = q1 * radix + q0;
1335
1336 return quotient;
1337#endif
1338}
1339
1340/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001341 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001342 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001343int 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 +00001344{
Paul Bakker23986e52011-04-24 08:57:21 +00001345 int ret;
1346 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001347 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001349 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1350 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001351
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001352 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1353 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001354
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001355 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001356 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001357 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1358 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001359 return( 0 );
1360 }
1361
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001362 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1363 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001364 X.s = Y.s = 1;
1365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1367 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1368 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1369 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001370
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001371 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001372 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001373 {
1374 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001375 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1376 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001377 }
1378 else k = 0;
1379
1380 n = X.n - 1;
1381 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001382 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001383
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001384 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001385 {
1386 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001387 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001388 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001389 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001390
1391 for( i = n; i > t ; i-- )
1392 {
1393 if( X.p[i] >= Y.p[t] )
1394 Z.p[i - t - 1] = ~0;
1395 else
1396 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001397 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1398 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001399 }
1400
1401 Z.p[i - t - 1]++;
1402 do
1403 {
1404 Z.p[i - t - 1]--;
1405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001407 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001408 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001409 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001410
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001411 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001412 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1413 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001414 T2.p[2] = X.p[i];
1415 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001416 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001417
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001418 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1419 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1420 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001421
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001422 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001423 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001424 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1425 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1426 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001427 Z.p[i - t - 1]--;
1428 }
1429 }
1430
1431 if( Q != NULL )
1432 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001433 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001434 Q->s = A->s * B->s;
1435 }
1436
1437 if( R != NULL )
1438 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001439 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001440 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001441 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001443 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001444 R->s = 1;
1445 }
1446
1447cleanup:
1448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001449 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1450 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001451
1452 return( ret );
1453}
1454
1455/*
1456 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001457 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001458int 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 +00001459{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001460 mbedtls_mpi _B;
1461 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001462
1463 p[0] = ( b < 0 ) ? -b : b;
1464 _B.s = ( b < 0 ) ? -1 : 1;
1465 _B.n = 1;
1466 _B.p = p;
1467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001468 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001469}
1470
1471/*
1472 * Modulo: R = A mod B
1473 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001474int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001475{
1476 int ret;
1477
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001478 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1479 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001481 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001483 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1484 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001485
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001486 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1487 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001488
1489cleanup:
1490
1491 return( ret );
1492}
1493
1494/*
1495 * Modulo: r = A mod b
1496 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001497int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001498{
Paul Bakker23986e52011-04-24 08:57:21 +00001499 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001500 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001501
1502 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001503 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001504
1505 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001507
1508 /*
1509 * handle trivial cases
1510 */
1511 if( b == 1 )
1512 {
1513 *r = 0;
1514 return( 0 );
1515 }
1516
1517 if( b == 2 )
1518 {
1519 *r = A->p[0] & 1;
1520 return( 0 );
1521 }
1522
1523 /*
1524 * general case
1525 */
Paul Bakker23986e52011-04-24 08:57:21 +00001526 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001527 {
Paul Bakker23986e52011-04-24 08:57:21 +00001528 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001529 y = ( y << biH ) | ( x >> biH );
1530 z = y / b;
1531 y -= z * b;
1532
1533 x <<= biH;
1534 y = ( y << biH ) | ( x >> biH );
1535 z = y / b;
1536 y -= z * b;
1537 }
1538
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001539 /*
1540 * If A is negative, then the current y represents a negative value.
1541 * Flipping it to the positive side.
1542 */
1543 if( A->s < 0 && y != 0 )
1544 y = b - y;
1545
Paul Bakker5121ce52009-01-03 21:22:43 +00001546 *r = y;
1547
1548 return( 0 );
1549}
1550
1551/*
1552 * Fast Montgomery initialization (thanks to Tom St Denis)
1553 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001554static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001555{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001556 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001557 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001558
1559 x = m0;
1560 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001561
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001562 for( i = biL; i >= 8; i /= 2 )
1563 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001564
1565 *mm = ~x + 1;
1566}
1567
1568/*
1569 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1570 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001571static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001572 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001573{
Paul Bakker23986e52011-04-24 08:57:21 +00001574 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001575 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001576
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001577 if( T->n < N->n + 1 || T->p == NULL )
1578 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1579
Paul Bakker5121ce52009-01-03 21:22:43 +00001580 memset( T->p, 0, T->n * ciL );
1581
1582 d = T->p;
1583 n = N->n;
1584 m = ( B->n < n ) ? B->n : n;
1585
1586 for( i = 0; i < n; i++ )
1587 {
1588 /*
1589 * T = (T + u0*B + u1*N) / 2^biL
1590 */
1591 u0 = A->p[i];
1592 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1593
1594 mpi_mul_hlp( m, B->p, d, u0 );
1595 mpi_mul_hlp( n, N->p, d, u1 );
1596
1597 *d++ = u0; d[n + 1] = 0;
1598 }
1599
Paul Bakker66d5d072014-06-17 16:39:18 +02001600 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001601
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001602 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001603 mpi_sub_hlp( n, N->p, A->p );
1604 else
1605 /* prevent timing attacks */
1606 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001607
1608 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001609}
1610
1611/*
1612 * Montgomery reduction: A = A * R^-1 mod N
1613 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001614static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001615{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001616 mbedtls_mpi_uint z = 1;
1617 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001618
Paul Bakker8ddb6452013-02-27 14:56:33 +01001619 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001620 U.p = &z;
1621
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001622 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001623}
1624
1625/*
1626 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1627 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001628int 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 +00001629{
Paul Bakker23986e52011-04-24 08:57:21 +00001630 int ret;
1631 size_t wbits, wsize, one = 1;
1632 size_t i, j, nblimbs;
1633 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001634 mbedtls_mpi_uint ei, mm, state;
1635 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001636 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001637
Hanno Becker930ec7d2018-03-09 10:48:00 +00001638 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001639 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001640
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001641 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1642 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001643
1644 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001645 * Init temps and window size
1646 */
1647 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001648 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1649 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001650 memset( W, 0, sizeof( W ) );
1651
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001652 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001653
1654 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1655 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1656
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001657 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1658 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001659
Paul Bakker5121ce52009-01-03 21:22:43 +00001660 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1662 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1663 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001664
1665 /*
Paul Bakker50546922012-05-19 08:40:49 +00001666 * Compensate for negative A (and correct at the end)
1667 */
1668 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001669 if( neg )
1670 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001672 Apos.s = 1;
1673 A = &Apos;
1674 }
1675
1676 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001677 * If 1st call, pre-compute R^2 mod N
1678 */
1679 if( _RR == NULL || _RR->p == NULL )
1680 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001681 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1682 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1683 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001684
1685 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001686 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001687 }
1688 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001689 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001690
1691 /*
1692 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1693 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001694 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1695 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001696 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001697 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001698
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001699 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001700
1701 /*
1702 * X = R^2 * R^-1 mod N = R mod N
1703 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001704 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001705 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001706
1707 if( wsize > 1 )
1708 {
1709 /*
1710 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1711 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001712 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001713
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001714 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1715 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001716
1717 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001718 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001719
Paul Bakker5121ce52009-01-03 21:22:43 +00001720 /*
1721 * W[i] = W[i - 1] * W[1]
1722 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001723 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001724 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001725 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1726 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001727
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001728 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001729 }
1730 }
1731
1732 nblimbs = E->n;
1733 bufsize = 0;
1734 nbits = 0;
1735 wbits = 0;
1736 state = 0;
1737
1738 while( 1 )
1739 {
1740 if( bufsize == 0 )
1741 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001742 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001743 break;
1744
Paul Bakker0d7702c2013-10-29 16:18:35 +01001745 nblimbs--;
1746
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001747 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001748 }
1749
1750 bufsize--;
1751
1752 ei = (E->p[nblimbs] >> bufsize) & 1;
1753
1754 /*
1755 * skip leading 0s
1756 */
1757 if( ei == 0 && state == 0 )
1758 continue;
1759
1760 if( ei == 0 && state == 1 )
1761 {
1762 /*
1763 * out of window, square X
1764 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001765 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001766 continue;
1767 }
1768
1769 /*
1770 * add ei to current window
1771 */
1772 state = 2;
1773
1774 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001775 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001776
1777 if( nbits == wsize )
1778 {
1779 /*
1780 * X = X^wsize R^-1 mod N
1781 */
1782 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001783 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001784
1785 /*
1786 * X = X * W[wbits] R^-1 mod N
1787 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001788 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001789
1790 state--;
1791 nbits = 0;
1792 wbits = 0;
1793 }
1794 }
1795
1796 /*
1797 * process the remaining bits
1798 */
1799 for( i = 0; i < nbits; i++ )
1800 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001801 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001802
1803 wbits <<= 1;
1804
Paul Bakker66d5d072014-06-17 16:39:18 +02001805 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001806 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001807 }
1808
1809 /*
1810 * X = A^E * R * R^-1 mod N = A^E mod N
1811 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001812 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001813
Hanno Beckera4af1c42017-04-18 09:07:45 +01001814 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001815 {
1816 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001817 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001818 }
1819
Paul Bakker5121ce52009-01-03 21:22:43 +00001820cleanup:
1821
Paul Bakker66d5d072014-06-17 16:39:18 +02001822 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001823 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001824
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001825 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001826
Paul Bakker75a28602014-03-31 12:08:17 +02001827 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001828 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001829
1830 return( ret );
1831}
1832
Paul Bakker5121ce52009-01-03 21:22:43 +00001833/*
1834 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1835 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001836int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001837{
Paul Bakker23986e52011-04-24 08:57:21 +00001838 int ret;
1839 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001840 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001841
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001842 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001843
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1845 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001847 lz = mbedtls_mpi_lsb( &TA );
1848 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001849
Paul Bakker66d5d072014-06-17 16:39:18 +02001850 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001851 lz = lzt;
1852
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001853 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1854 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001855
Paul Bakker5121ce52009-01-03 21:22:43 +00001856 TA.s = TB.s = 1;
1857
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001858 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001859 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001860 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1861 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001862
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001863 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001864 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001865 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1866 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001867 }
1868 else
1869 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001870 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1871 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001872 }
1873 }
1874
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001875 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1876 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001877
1878cleanup:
1879
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001881
1882 return( ret );
1883}
1884
Paul Bakker33dc46b2014-04-30 16:11:39 +02001885/*
1886 * Fill X with size bytes of random.
1887 *
1888 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001889 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001890 * deterministic, eg for tests).
1891 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001892int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001893 int (*f_rng)(void *, unsigned char *, size_t),
1894 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001895{
Paul Bakker23986e52011-04-24 08:57:21 +00001896 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001897 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001898
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001899 if( size > MBEDTLS_MPI_MAX_SIZE )
1900 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001901
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001902 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1903 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001904
1905cleanup:
Hanno Becker88807112017-10-18 12:41:30 +01001906 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001907 return( ret );
1908}
1909
Paul Bakker5121ce52009-01-03 21:22:43 +00001910/*
1911 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1912 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001913int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001914{
1915 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001916 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001917
Hanno Becker4bcb4912017-04-18 15:49:39 +01001918 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001919 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001920
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001921 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1922 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1923 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001924
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001925 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001926
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001927 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001928 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001930 goto cleanup;
1931 }
1932
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001933 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1934 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1935 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1936 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001937
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001938 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1939 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1940 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1941 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001942
1943 do
1944 {
1945 while( ( TU.p[0] & 1 ) == 0 )
1946 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001947 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001948
1949 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1950 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001951 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1952 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001953 }
1954
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001955 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1956 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001957 }
1958
1959 while( ( TV.p[0] & 1 ) == 0 )
1960 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001961 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001962
1963 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1964 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001965 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1966 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001967 }
1968
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001969 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1970 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001971 }
1972
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001973 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001974 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001975 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1976 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1977 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001978 }
1979 else
1980 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001981 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1982 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1983 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001984 }
1985 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001986 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001987
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1989 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001990
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001991 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1992 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001993
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001994 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001995
1996cleanup:
1997
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001998 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1999 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2000 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002001
2002 return( ret );
2003}
2004
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002005#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002006
Paul Bakker5121ce52009-01-03 21:22:43 +00002007static const int small_prime[] =
2008{
2009 3, 5, 7, 11, 13, 17, 19, 23,
2010 29, 31, 37, 41, 43, 47, 53, 59,
2011 61, 67, 71, 73, 79, 83, 89, 97,
2012 101, 103, 107, 109, 113, 127, 131, 137,
2013 139, 149, 151, 157, 163, 167, 173, 179,
2014 181, 191, 193, 197, 199, 211, 223, 227,
2015 229, 233, 239, 241, 251, 257, 263, 269,
2016 271, 277, 281, 283, 293, 307, 311, 313,
2017 317, 331, 337, 347, 349, 353, 359, 367,
2018 373, 379, 383, 389, 397, 401, 409, 419,
2019 421, 431, 433, 439, 443, 449, 457, 461,
2020 463, 467, 479, 487, 491, 499, 503, 509,
2021 521, 523, 541, 547, 557, 563, 569, 571,
2022 577, 587, 593, 599, 601, 607, 613, 617,
2023 619, 631, 641, 643, 647, 653, 659, 661,
2024 673, 677, 683, 691, 701, 709, 719, 727,
2025 733, 739, 743, 751, 757, 761, 769, 773,
2026 787, 797, 809, 811, 821, 823, 827, 829,
2027 839, 853, 857, 859, 863, 877, 881, 883,
2028 887, 907, 911, 919, 929, 937, 941, 947,
2029 953, 967, 971, 977, 983, 991, 997, -103
2030};
2031
2032/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002033 * Small divisors test (X must be positive)
2034 *
2035 * Return values:
2036 * 0: no small factor (possible prime, more tests needed)
2037 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002038 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002039 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002040 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002041static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002042{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002043 int ret = 0;
2044 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002045 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002046
Paul Bakker5121ce52009-01-03 21:22:43 +00002047 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002048 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002049
2050 for( i = 0; small_prime[i] > 0; i++ )
2051 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002053 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002054
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002055 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002056
2057 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002059 }
2060
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002061cleanup:
2062 return( ret );
2063}
2064
2065/*
2066 * Miller-Rabin pseudo-primality test (HAC 4.24)
2067 */
Janos Follath72d555d2018-09-03 14:45:23 +01002068static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002069 int (*f_rng)(void *, unsigned char *, size_t),
2070 void *p_rng )
2071{
Pascal Junodb99183d2015-03-11 16:49:45 +01002072 int ret, count;
Janos Follath72d555d2018-09-03 14:45:23 +01002073 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002074 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002075
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2077 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002078
Paul Bakker5121ce52009-01-03 21:22:43 +00002079 /*
2080 * W = |X| - 1
2081 * R = W >> lsb( W )
2082 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002083 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2084 s = mbedtls_mpi_lsb( &W );
2085 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2086 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002087
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002088 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002089
Janos Follath72d555d2018-09-03 14:45:23 +01002090 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002091 {
2092 /*
2093 * pick a random A, 1 < A < |X| - 1
2094 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002095 count = 0;
2096 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002097 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002098
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002099 j = mbedtls_mpi_bitlen( &A );
2100 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002101 if (j > k) {
Darryl Green56d7cc42018-10-02 13:21:35 +01002102 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002103 }
2104
2105 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002106 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002107 }
2108
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002109 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2110 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002111
2112 /*
2113 * A = A^R mod |X|
2114 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002115 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002116
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002117 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2118 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002119 continue;
2120
2121 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002122 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002123 {
2124 /*
2125 * A = A * A mod |X|
2126 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002127 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2128 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002129
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002130 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002131 break;
2132
2133 j++;
2134 }
2135
2136 /*
2137 * not prime if A != |X| - 1 or A == 1
2138 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002139 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2140 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002141 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002142 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002143 break;
2144 }
2145 }
2146
2147cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002148 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2149 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002150
2151 return( ret );
2152}
2153
2154/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002155 * Pseudo-primality test: small factors, then Miller-Rabin
2156 */
Darryl Green94759f62018-10-16 15:09:19 +01002157static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002158 int (*f_rng)(void *, unsigned char *, size_t),
2159 void *p_rng )
2160{
2161 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002162 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002163
2164 XX.s = 1;
2165 XX.n = X->n;
2166 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002167
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002168 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2169 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2170 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002171
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002172 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002173 return( 0 );
2174
2175 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2176 {
2177 if( ret == 1 )
2178 return( 0 );
2179
2180 return( ret );
2181 }
2182
Janos Follath72d555d2018-09-03 14:45:23 +01002183 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2184}
2185
2186/*
2187 * Pseudo-primality test, error probability 2^-80
2188 */
2189int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2190 int (*f_rng)(void *, unsigned char *, size_t),
2191 void *p_rng )
2192{
2193 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002194}
2195
2196/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002197 * Prime number generation
2198 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002199int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002200 int (*f_rng)(void *, unsigned char *, size_t),
2201 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002202{
Paul Bakker23986e52011-04-24 08:57:21 +00002203 int ret;
2204 size_t k, n;
Janos Follath72d555d2018-09-03 14:45:23 +01002205 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206 mbedtls_mpi_uint r;
2207 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002209 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2210 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002211
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002212 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002213
2214 n = BITS_TO_LIMBS( nbits );
2215
Janos Follath72d555d2018-09-03 14:45:23 +01002216 /*
2217 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2218 */
2219 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2220 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2221 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2222
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002223 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002224
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002225 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002226 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002227
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002228 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002229
2230 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002231
2232 if( dh_flag == 0 )
2233 {
Janos Follath72d555d2018-09-03 14:45:23 +01002234 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002235 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002236 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002237 goto cleanup;
2238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002239 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002240 }
2241 }
2242 else
2243 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002244 /*
2245 * An necessary condition for Y and X = 2Y + 1 to be prime
2246 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2247 * Make sure it is satisfied, while keeping X = 3 mod 4
2248 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002249
2250 X->p[0] |= 2;
2251
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002252 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002253 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002254 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002255 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002256 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002257
2258 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002259 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2260 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002261
2262 while( 1 )
2263 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002264 /*
2265 * First, check small factors for X and Y
2266 * before doing Miller-Rabin on any of them
2267 */
2268 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2269 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath72d555d2018-09-03 14:45:23 +01002270 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2271 == 0 &&
2272 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2273 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002274 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002275 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002276 }
2277
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002278 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002279 goto cleanup;
2280
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002281 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002282 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002283 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2284 * so up Y by 6 and X by 12.
2285 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002286 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2287 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002288 }
2289 }
2290
2291cleanup:
2292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002293 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002294
2295 return( ret );
2296}
2297
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002298#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002299
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002300#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002301
Paul Bakker23986e52011-04-24 08:57:21 +00002302#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002303
2304static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2305{
2306 { 693, 609, 21 },
2307 { 1764, 868, 28 },
2308 { 768454923, 542167814, 1 }
2309};
2310
Paul Bakker5121ce52009-01-03 21:22:43 +00002311/*
2312 * Checkup routine
2313 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002314int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002315{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002316 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002317 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002319 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2320 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002321
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002322 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002323 "EFE021C2645FD1DC586E69184AF4A31E" \
2324 "D5F53E93B5F123FA41680867BA110131" \
2325 "944FE7952E2517337780CB0DB80E61AA" \
2326 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2327
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002328 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002329 "B2E7EFD37075B9F03FF989C7C5051C20" \
2330 "34D2A323810251127E7BF8625A4F49A5" \
2331 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2332 "5B5C25763222FEFCCFC38B832366C29E" ) );
2333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002334 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002335 "0066A198186C18C10B2F5ED9B522752A" \
2336 "9830B69916E535C8F047518A889A43A5" \
2337 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2338
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002339 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002342 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2343 "9E857EA95A03512E2BAE7391688D264A" \
2344 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2345 "8001B72E848A38CAE1C65F78E56ABDEF" \
2346 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2347 "ECF677152EF804370C1A305CAF3B5BF1" \
2348 "30879B56C61DE584A0F53A2447A51E" ) );
2349
2350 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002351 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002352
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002354 {
2355 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002356 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002357
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002358 ret = 1;
2359 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002360 }
2361
2362 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002363 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002364
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002365 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002366
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002368 "256567336059E52CAE22925474705F39A94" ) );
2369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002370 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002371 "6613F26162223DF488E9CD48CC132C7A" \
2372 "0AC93C701B001B092E4E5B9F73BCD27B" \
2373 "9EE50D0657C77F374E903CDFA4C642" ) );
2374
2375 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002378 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2379 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002380 {
2381 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002382 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002383
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002384 ret = 1;
2385 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002386 }
2387
2388 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002389 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002390
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002391 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002393 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002394 "36E139AEA55215609D2816998ED020BB" \
2395 "BD96C37890F65171D948E9BC7CBAA4D9" \
2396 "325D24D6A3C12710F10A09FA08AB87" ) );
2397
2398 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002399 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002400
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002401 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002402 {
2403 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002404 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002405
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002406 ret = 1;
2407 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002408 }
2409
2410 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002411 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002413 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002414
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002415 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002416 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2417 "C3DBA76456363A10869622EAC2DD84EC" \
2418 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2419
2420 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002421 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002422
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002423 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002424 {
2425 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002426 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002427
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002428 ret = 1;
2429 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002430 }
2431
2432 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002433 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002434
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002435 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002436 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002437
Paul Bakker66d5d072014-06-17 16:39:18 +02002438 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002439 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2441 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002443 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002445 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002446 {
2447 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002448 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002449
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002450 ret = 1;
2451 goto cleanup;
2452 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002453 }
2454
2455 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002456 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002457
Paul Bakker5121ce52009-01-03 21:22:43 +00002458cleanup:
2459
2460 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002461 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002463 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2464 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002465
2466 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002467 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002468
2469 return( ret );
2470}
2471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002472#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002473
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002474#endif /* MBEDTLS_BIGNUM_C */