blob: 142aeaca26aca3181f7dda74be6711f25d0146e8 [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 Butcherea303e32015-11-26 23:43:34 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcherea303e32015-11-26 23:43:34 +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 Butcherea303e32015-11-26 23:43:34 +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 Butcher7ebe2782015-12-28 00:05:30 +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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020062static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020063 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
64}
65
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020066#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000067#define biL (ciL << 3) /* bits in limb */
68#define biH (ciL << 2) /* half limb size */
69
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010070#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
71
Paul Bakker5121ce52009-01-03 21:22:43 +000072/*
73 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020074 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000075 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020076#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
77#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000078
79/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000080 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000081 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000083{
Paul Bakker6c591fa2011-05-05 11:49:20 +000084 if( X == NULL )
85 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000086
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 X->s = 1;
88 X->n = 0;
89 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000090}
91
92/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000094 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020095void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000096{
Paul Bakker6c591fa2011-05-05 11:49:20 +000097 if( X == NULL )
98 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000099
Paul Bakker6c591fa2011-05-05 11:49:20 +0000100 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000101 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200102 mbedtls_zeroize( X->p, X->n * ciL );
103 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000104 }
105
Paul Bakker6c591fa2011-05-05 11:49:20 +0000106 X->s = 1;
107 X->n = 0;
108 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000109}
110
111/*
112 * Enlarge to the specified number of limbs
113 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200114int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000115{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000117
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200118 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200119 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000120
Paul Bakker5121ce52009-01-03 21:22:43 +0000121 if( X->n < nblimbs )
122 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200123 if( ( p = mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200124 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000125
Paul Bakker5121ce52009-01-03 21:22:43 +0000126 if( X->p != NULL )
127 {
128 memcpy( p, X->p, X->n * ciL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 mbedtls_zeroize( X->p, X->n * ciL );
130 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000131 }
132
133 X->n = nblimbs;
134 X->p = p;
135 }
136
137 return( 0 );
138}
139
140/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100141 * Resize down as much as possible,
142 * while keeping at least the specified number of limbs
143 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100145{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100147 size_t i;
148
149 /* Actually resize up in this case */
150 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152
153 for( i = X->n - 1; i > 0; i-- )
154 if( X->p[i] != 0 )
155 break;
156 i++;
157
158 if( i < nblimbs )
159 i = nblimbs;
160
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200161 if( ( p = mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200162 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100164 if( X->p != NULL )
165 {
166 memcpy( p, X->p, i * ciL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200167 mbedtls_zeroize( X->p, X->n * ciL );
168 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100169 }
170
171 X->n = i;
172 X->p = p;
173
174 return( 0 );
175}
176
177/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000178 * Copy the contents of Y into X
179 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000181{
Paul Bakker23986e52011-04-24 08:57:21 +0000182 int ret;
183 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000184
185 if( X == Y )
186 return( 0 );
187
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200188 if( Y->p == NULL )
189 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200191 return( 0 );
192 }
193
Paul Bakker5121ce52009-01-03 21:22:43 +0000194 for( i = Y->n - 1; i > 0; i-- )
195 if( Y->p[i] != 0 )
196 break;
197 i++;
198
199 X->s = Y->s;
200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200201 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000202
203 memset( X->p, 0, X->n * ciL );
204 memcpy( X->p, Y->p, i * ciL );
205
206cleanup:
207
208 return( ret );
209}
210
211/*
212 * Swap the contents of X and Y
213 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200214void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000215{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218 memcpy( &T, X, sizeof( mbedtls_mpi ) );
219 memcpy( X, Y, sizeof( mbedtls_mpi ) );
220 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000221}
222
223/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100224 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100225 * about whether the assignment was made or not.
226 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100227 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100229{
230 int ret = 0;
231 size_t i;
232
Pascal Junodb99183d2015-03-11 16:49:45 +0100233 /* make sure assign is 0 or 1 in a time-constant manner */
234 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100235
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100237
Paul Bakker66d5d072014-06-17 16:39:18 +0200238 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100239
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100240 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200241 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100242
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100243 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200244 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100245
246cleanup:
247 return( ret );
248}
249
250/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100251 * Conditionally swap X and Y, without leaking information
252 * about whether the swap was made or not.
253 * Here it is not ok to simply swap the pointers, which whould lead to
254 * different memory access patterns when X and Y are used afterwards.
255 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100257{
258 int ret, s;
259 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100261
262 if( X == Y )
263 return( 0 );
264
Pascal Junodb99183d2015-03-11 16:49:45 +0100265 /* make sure swap is 0 or 1 in a time-constant manner */
266 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
269 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100270
271 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200272 X->s = X->s * ( 1 - swap ) + Y->s * swap;
273 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274
275
276 for( i = 0; i < X->n; i++ )
277 {
278 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200279 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
280 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100281 }
282
283cleanup:
284 return( ret );
285}
286
287/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000288 * Set value from integer
289 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200290int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000291{
292 int ret;
293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000295 memset( X->p, 0, X->n * ciL );
296
297 X->p[0] = ( z < 0 ) ? -z : z;
298 X->s = ( z < 0 ) ? -1 : 1;
299
300cleanup:
301
302 return( ret );
303}
304
305/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000306 * Get a specific bit
307 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000309{
310 if( X->n * biL <= pos )
311 return( 0 );
312
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200313 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000314}
315
316/*
317 * Set a bit to a specific value of 0 or 1
318 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200319int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000320{
321 int ret = 0;
322 size_t off = pos / biL;
323 size_t idx = pos % biL;
324
325 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200327
Paul Bakker2f5947e2011-05-18 15:47:11 +0000328 if( X->n * biL <= pos )
329 {
330 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200331 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200333 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000334 }
335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
337 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338
339cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200340
Paul Bakker2f5947e2011-05-18 15:47:11 +0000341 return( ret );
342}
343
344/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200345 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000346 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000348{
Paul Bakker23986e52011-04-24 08:57:21 +0000349 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000350
351 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000352 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000353 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
354 return( count );
355
356 return( 0 );
357}
358
359/*
Simon Butcherea303e32015-11-26 23:43:34 +0000360 * Count leading zero bits in a given integer
361 */
362static size_t mbedtls_clz( const mbedtls_mpi_uint x )
363{
364 size_t j;
Manuel Pégourié-Gonnard3eab29a2015-12-01 09:31:52 +0100365 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcherea303e32015-11-26 23:43:34 +0000366
367 for( j = 0; j < biL; j++ )
368 {
369 if( x & mask ) break;
370
371 mask >>= 1;
372 }
373
374 return j;
375}
376
377/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200378 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200380size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000381{
Paul Bakker23986e52011-04-24 08:57:21 +0000382 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000383
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200384 if( X->n == 0 )
385 return( 0 );
386
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 for( i = X->n - 1; i > 0; i-- )
388 if( X->p[i] != 0 )
389 break;
390
Simon Butcherea303e32015-11-26 23:43:34 +0000391 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000392
Paul Bakker23986e52011-04-24 08:57:21 +0000393 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000394}
395
396/*
397 * Return the total size in bytes
398 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000400{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200401 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000402}
403
404/*
405 * Convert an ASCII character to digit value
406 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000408{
409 *d = 255;
410
411 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
412 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
413 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
414
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415 if( *d >= (mbedtls_mpi_uint) radix )
416 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
418 return( 0 );
419}
420
421/*
422 * Import from an ASCII string
423 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000425{
Paul Bakker23986e52011-04-24 08:57:21 +0000426 int ret;
427 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 mbedtls_mpi_uint d;
429 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000430
431 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000435
Paul Bakkerff60ee62010-03-16 21:09:09 +0000436 slen = strlen( s );
437
Paul Bakker5121ce52009-01-03 21:22:43 +0000438 if( radix == 16 )
439 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100440 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200441 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
442
Paul Bakkerff60ee62010-03-16 21:09:09 +0000443 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
446 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000447
Paul Bakker23986e52011-04-24 08:57:21 +0000448 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000449 {
Paul Bakker23986e52011-04-24 08:57:21 +0000450 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000451 {
452 X->s = -1;
453 break;
454 }
455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200457 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 }
459 }
460 else
461 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000463
Paul Bakkerff60ee62010-03-16 21:09:09 +0000464 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000465 {
466 if( i == 0 && s[i] == '-' )
467 {
468 X->s = -1;
469 continue;
470 }
471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
473 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000474
475 if( X->s == 1 )
476 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000478 }
479 else
480 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000482 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000483 }
484 }
485
486cleanup:
487
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200488 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000489
490 return( ret );
491}
492
493/*
494 * Helper to write the digits high-order first
495 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000497{
498 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000500
501 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
505 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
508 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000509
510 if( r < 10 )
511 *(*p)++ = (char)( r + 0x30 );
512 else
513 *(*p)++ = (char)( r + 0x37 );
514
515cleanup:
516
517 return( ret );
518}
519
520/*
521 * Export into an ASCII string
522 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100523int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
524 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000525{
Paul Bakker23986e52011-04-24 08:57:21 +0000526 int ret = 0;
527 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000528 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000530
531 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000533
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200534 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000535 if( radix >= 4 ) n >>= 1;
536 if( radix >= 16 ) n >>= 1;
Andres AGe0545c32017-01-06 13:17:35 +0000537 /*
538 * Round up the buffer length to an even value to ensure that there is
539 * enough room for hexadecimal values that can be represented in an odd
540 * number of digits.
541 */
542 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000543
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100544 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000545 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100546 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200547 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000548 }
549
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100550 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200551 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000552
553 if( X->s == -1 )
554 *p++ = '-';
555
556 if( radix == 16 )
557 {
Paul Bakker23986e52011-04-24 08:57:21 +0000558 int c;
559 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000560
Paul Bakker23986e52011-04-24 08:57:21 +0000561 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000562 {
Paul Bakker23986e52011-04-24 08:57:21 +0000563 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000564 {
Paul Bakker23986e52011-04-24 08:57:21 +0000565 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000566
Paul Bakker6c343d72014-07-10 14:36:19 +0200567 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000568 continue;
569
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000570 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000571 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000572 k = 1;
573 }
574 }
575 }
576 else
577 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000579
580 if( T.s == -1 )
581 T.s = 1;
582
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200583 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000584 }
585
586 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100587 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000588
589cleanup:
590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000592
593 return( ret );
594}
595
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200596#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000597/*
598 * Read X from an opened file
599 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200600int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000601{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000603 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000604 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000605 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000606 * Buffer should have space for (short) label and decimal formatted MPI,
607 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000608 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200609 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000610
611 memset( s, 0, sizeof( s ) );
612 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000614
615 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000616 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000618
Hanno Becker4195e802017-04-26 11:46:46 +0100619 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
620 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000621
622 p = s + slen;
Hanno Becker4195e802017-04-26 11:46:46 +0100623 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000624 if( mpi_get_digit( &d, radix, *p ) != 0 )
625 break;
626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200627 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000628}
629
630/*
631 * Write X into an opened file (or stdout if fout == NULL)
632 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200633int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000634{
Paul Bakker23986e52011-04-24 08:57:21 +0000635 int ret;
636 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000637 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000638 * Buffer should have space for (short) label and decimal formatted MPI,
639 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000640 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000642
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100643 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000644
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100645 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000646
647 if( p == NULL ) p = "";
648
649 plen = strlen( p );
650 slen = strlen( s );
651 s[slen++] = '\r';
652 s[slen++] = '\n';
653
654 if( fout != NULL )
655 {
656 if( fwrite( p, 1, plen, fout ) != plen ||
657 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000659 }
660 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000662
663cleanup:
664
665 return( ret );
666}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000668
669/*
670 * Import X from unsigned binary data, big endian
671 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000673{
Paul Bakker23986e52011-04-24 08:57:21 +0000674 int ret;
675 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000676
677 for( n = 0; n < buflen; n++ )
678 if( buf[n] != 0 )
679 break;
680
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
682 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000683
Paul Bakker23986e52011-04-24 08:57:21 +0000684 for( i = buflen, j = 0; i > n; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000686
687cleanup:
688
689 return( ret );
690}
691
692/*
693 * Export X into unsigned binary data, big endian
694 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000696{
Paul Bakker23986e52011-04-24 08:57:21 +0000697 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200699 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000700
701 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200702 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000703
704 memset( buf, 0, buflen );
705
706 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
707 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
708
709 return( 0 );
710}
711
712/*
713 * Left-shift: X <<= count
714 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200715int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000716{
Paul Bakker23986e52011-04-24 08:57:21 +0000717 int ret;
718 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000720
721 v0 = count / (biL );
722 t1 = count & (biL - 1);
723
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200724 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000725
Paul Bakkerf9688572011-05-05 10:00:45 +0000726 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200727 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000728
729 ret = 0;
730
731 /*
732 * shift by count / limb_size
733 */
734 if( v0 > 0 )
735 {
Paul Bakker23986e52011-04-24 08:57:21 +0000736 for( i = X->n; i > v0; i-- )
737 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000738
Paul Bakker23986e52011-04-24 08:57:21 +0000739 for( ; i > 0; i-- )
740 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000741 }
742
743 /*
744 * shift by count % limb_size
745 */
746 if( t1 > 0 )
747 {
748 for( i = v0; i < X->n; i++ )
749 {
750 r1 = X->p[i] >> (biL - t1);
751 X->p[i] <<= t1;
752 X->p[i] |= r0;
753 r0 = r1;
754 }
755 }
756
757cleanup:
758
759 return( ret );
760}
761
762/*
763 * Right-shift: X >>= count
764 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200765int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000766{
Paul Bakker23986e52011-04-24 08:57:21 +0000767 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200768 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000769
770 v0 = count / biL;
771 v1 = count & (biL - 1);
772
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100773 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200774 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100775
Paul Bakker5121ce52009-01-03 21:22:43 +0000776 /*
777 * shift by count / limb_size
778 */
779 if( v0 > 0 )
780 {
781 for( i = 0; i < X->n - v0; i++ )
782 X->p[i] = X->p[i + v0];
783
784 for( ; i < X->n; i++ )
785 X->p[i] = 0;
786 }
787
788 /*
789 * shift by count % limb_size
790 */
791 if( v1 > 0 )
792 {
Paul Bakker23986e52011-04-24 08:57:21 +0000793 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000794 {
Paul Bakker23986e52011-04-24 08:57:21 +0000795 r1 = X->p[i - 1] << (biL - v1);
796 X->p[i - 1] >>= v1;
797 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000798 r0 = r1;
799 }
800 }
801
802 return( 0 );
803}
804
805/*
806 * Compare unsigned values
807 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200808int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000809{
Paul Bakker23986e52011-04-24 08:57:21 +0000810 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000811
Paul Bakker23986e52011-04-24 08:57:21 +0000812 for( i = X->n; i > 0; i-- )
813 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000814 break;
815
Paul Bakker23986e52011-04-24 08:57:21 +0000816 for( j = Y->n; j > 0; j-- )
817 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000818 break;
819
Paul Bakker23986e52011-04-24 08:57:21 +0000820 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000821 return( 0 );
822
823 if( i > j ) return( 1 );
824 if( j > i ) return( -1 );
825
Paul Bakker23986e52011-04-24 08:57:21 +0000826 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000827 {
Paul Bakker23986e52011-04-24 08:57:21 +0000828 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
829 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000830 }
831
832 return( 0 );
833}
834
835/*
836 * Compare signed values
837 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200838int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000839{
Paul Bakker23986e52011-04-24 08:57:21 +0000840 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000841
Paul Bakker23986e52011-04-24 08:57:21 +0000842 for( i = X->n; i > 0; i-- )
843 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000844 break;
845
Paul Bakker23986e52011-04-24 08:57:21 +0000846 for( j = Y->n; j > 0; j-- )
847 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000848 break;
849
Paul Bakker23986e52011-04-24 08:57:21 +0000850 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000851 return( 0 );
852
853 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000854 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000855
856 if( X->s > 0 && Y->s < 0 ) return( 1 );
857 if( Y->s > 0 && X->s < 0 ) return( -1 );
858
Paul Bakker23986e52011-04-24 08:57:21 +0000859 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000860 {
Paul Bakker23986e52011-04-24 08:57:21 +0000861 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
862 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000863 }
864
865 return( 0 );
866}
867
868/*
869 * Compare signed values
870 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200871int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000872{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200873 mbedtls_mpi Y;
874 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000875
876 *p = ( z < 0 ) ? -z : z;
877 Y.s = ( z < 0 ) ? -1 : 1;
878 Y.n = 1;
879 Y.p = p;
880
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200881 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000882}
883
884/*
885 * Unsigned addition: X = |A| + |B| (HAC 14.7)
886 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200887int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000888{
Paul Bakker23986e52011-04-24 08:57:21 +0000889 int ret;
890 size_t i, j;
Janos Follath79a1da62015-10-30 17:43:11 +0100891 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000892
893 if( X == B )
894 {
Janos Follath79a1da62015-10-30 17:43:11 +0100895 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000896 }
897
898 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200899 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200900
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000901 /*
902 * X should always be positive as a result of unsigned additions.
903 */
904 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000905
Paul Bakker23986e52011-04-24 08:57:21 +0000906 for( j = B->n; j > 0; j-- )
907 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000908 break;
909
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200910 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000911
912 o = B->p; p = X->p; c = 0;
913
Janos Follath79a1da62015-10-30 17:43:11 +0100914 /*
915 * tmp is used because it might happen that p == o
916 */
Paul Bakker23986e52011-04-24 08:57:21 +0000917 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000918 {
Janos Follath79a1da62015-10-30 17:43:11 +0100919 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000920 *p += c; c = ( *p < c );
Janos Follath79a1da62015-10-30 17:43:11 +0100921 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000922 }
923
924 while( c != 0 )
925 {
926 if( i >= X->n )
927 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200928 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000929 p = X->p + i;
930 }
931
Paul Bakker2d319fd2012-09-16 21:34:26 +0000932 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000933 }
934
935cleanup:
936
937 return( ret );
938}
939
940/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000942 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200943static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000944{
Paul Bakker23986e52011-04-24 08:57:21 +0000945 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200946 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000947
948 for( i = c = 0; i < n; i++, s++, d++ )
949 {
950 z = ( *d < c ); *d -= c;
951 c = ( *d < *s ) + z; *d -= *s;
952 }
953
954 while( c != 0 )
955 {
956 z = ( *d < c ); *d -= c;
957 c = z; i++; d++;
958 }
959}
960
961/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100962 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000963 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200964int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000965{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200966 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000967 int ret;
968 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000969
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200970 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
971 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000972
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200973 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000974
975 if( X == B )
976 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000978 B = &TB;
979 }
980
981 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200982 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000983
Paul Bakker1ef7a532009-06-20 10:50:55 +0000984 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100985 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000986 */
987 X->s = 1;
988
Paul Bakker5121ce52009-01-03 21:22:43 +0000989 ret = 0;
990
Paul Bakker23986e52011-04-24 08:57:21 +0000991 for( n = B->n; n > 0; n-- )
992 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000993 break;
994
Paul Bakker23986e52011-04-24 08:57:21 +0000995 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000996
997cleanup:
998
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200999 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001000
1001 return( ret );
1002}
1003
1004/*
1005 * Signed addition: X = A + B
1006 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001007int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001008{
1009 int ret, s = A->s;
1010
1011 if( A->s * B->s < 0 )
1012 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001013 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001014 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001015 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001016 X->s = s;
1017 }
1018 else
1019 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001020 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001021 X->s = -s;
1022 }
1023 }
1024 else
1025 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001026 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001027 X->s = s;
1028 }
1029
1030cleanup:
1031
1032 return( ret );
1033}
1034
1035/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001036 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001037 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001038int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001039{
1040 int ret, s = A->s;
1041
1042 if( A->s * B->s > 0 )
1043 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001044 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001045 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001046 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001047 X->s = s;
1048 }
1049 else
1050 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001051 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001052 X->s = -s;
1053 }
1054 }
1055 else
1056 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001057 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001058 X->s = s;
1059 }
1060
1061cleanup:
1062
1063 return( ret );
1064}
1065
1066/*
1067 * Signed addition: X = A + b
1068 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001069int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001070{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001071 mbedtls_mpi _B;
1072 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001073
1074 p[0] = ( b < 0 ) ? -b : b;
1075 _B.s = ( b < 0 ) ? -1 : 1;
1076 _B.n = 1;
1077 _B.p = p;
1078
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001079 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001080}
1081
1082/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001083 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001084 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001085int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001086{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001087 mbedtls_mpi _B;
1088 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001089
1090 p[0] = ( b < 0 ) ? -b : b;
1091 _B.s = ( b < 0 ) ? -1 : 1;
1092 _B.n = 1;
1093 _B.p = p;
1094
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001095 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001096}
1097
1098/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001099 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001100 */
1101static
1102#if defined(__APPLE__) && defined(__arm__)
1103/*
1104 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1105 * appears to need this to prevent bad ARM code generation at -O3.
1106 */
1107__attribute__ ((noinline))
1108#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001109void 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 +00001110{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001111 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001112
1113#if defined(MULADDC_HUIT)
1114 for( ; i >= 8; i -= 8 )
1115 {
1116 MULADDC_INIT
1117 MULADDC_HUIT
1118 MULADDC_STOP
1119 }
1120
1121 for( ; i > 0; i-- )
1122 {
1123 MULADDC_INIT
1124 MULADDC_CORE
1125 MULADDC_STOP
1126 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001127#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001128 for( ; i >= 16; i -= 16 )
1129 {
1130 MULADDC_INIT
1131 MULADDC_CORE MULADDC_CORE
1132 MULADDC_CORE MULADDC_CORE
1133 MULADDC_CORE MULADDC_CORE
1134 MULADDC_CORE MULADDC_CORE
1135
1136 MULADDC_CORE MULADDC_CORE
1137 MULADDC_CORE MULADDC_CORE
1138 MULADDC_CORE MULADDC_CORE
1139 MULADDC_CORE MULADDC_CORE
1140 MULADDC_STOP
1141 }
1142
1143 for( ; i >= 8; i -= 8 )
1144 {
1145 MULADDC_INIT
1146 MULADDC_CORE MULADDC_CORE
1147 MULADDC_CORE MULADDC_CORE
1148
1149 MULADDC_CORE MULADDC_CORE
1150 MULADDC_CORE MULADDC_CORE
1151 MULADDC_STOP
1152 }
1153
1154 for( ; i > 0; i-- )
1155 {
1156 MULADDC_INIT
1157 MULADDC_CORE
1158 MULADDC_STOP
1159 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001160#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001161
1162 t++;
1163
1164 do {
1165 *d += c; c = ( *d < c ); d++;
1166 }
1167 while( c != 0 );
1168}
1169
1170/*
1171 * Baseline multiplication: X = A * B (HAC 14.12)
1172 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001173int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001174{
Paul Bakker23986e52011-04-24 08:57:21 +00001175 int ret;
1176 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001177 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001178
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001179 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001181 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1182 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001183
Paul Bakker23986e52011-04-24 08:57:21 +00001184 for( i = A->n; i > 0; i-- )
1185 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001186 break;
1187
Paul Bakker23986e52011-04-24 08:57:21 +00001188 for( j = B->n; j > 0; j-- )
1189 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001190 break;
1191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001192 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1193 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001194
Paul Bakker23986e52011-04-24 08:57:21 +00001195 for( i++; j > 0; j-- )
1196 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001197
1198 X->s = A->s * B->s;
1199
1200cleanup:
1201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001202 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001203
1204 return( ret );
1205}
1206
1207/*
1208 * Baseline multiplication: X = A * b
1209 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001210int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001211{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001212 mbedtls_mpi _B;
1213 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001214
1215 _B.s = 1;
1216 _B.n = 1;
1217 _B.p = p;
1218 p[0] = b;
1219
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001220 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001221}
1222
1223/*
Simon Butcher7ebe2782015-12-28 00:05:30 +00001224 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1225 * mbedtls_mpi_uint divisor, d
Simon Butcherea303e32015-11-26 23:43:34 +00001226 */
Simon Butcher7ebe2782015-12-28 00:05:30 +00001227static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1228 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcherea303e32015-11-26 23:43:34 +00001229{
Manuel Pégourié-Gonnard5a8396e2015-12-01 10:27:00 +01001230#if defined(MBEDTLS_HAVE_UDBL)
1231 mbedtls_t_udbl dividend, quotient;
Simon Butcher7ebe2782015-12-28 00:05:30 +00001232#else
Simon Butcher61891752016-01-03 00:24:34 +00001233 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1234 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcher7ebe2782015-12-28 00:05:30 +00001235 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1236 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher61891752016-01-03 00:24:34 +00001237 size_t s;
Manuel Pégourié-Gonnard5a8396e2015-12-01 10:27:00 +01001238#endif
1239
Simon Butcherea303e32015-11-26 23:43:34 +00001240 /*
1241 * Check for overflow
1242 */
Simon Butcher7ebe2782015-12-28 00:05:30 +00001243 if( 0 == d || u1 >= d )
Simon Butcherea303e32015-11-26 23:43:34 +00001244 {
Simon Butcher7ebe2782015-12-28 00:05:30 +00001245 if (r != NULL) *r = ~0;
Simon Butcherea303e32015-11-26 23:43:34 +00001246
Simon Butcher7ebe2782015-12-28 00:05:30 +00001247 return ( ~0 );
Simon Butcherea303e32015-11-26 23:43:34 +00001248 }
1249
1250#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcherea303e32015-11-26 23:43:34 +00001251 dividend = (mbedtls_t_udbl) u1 << biL;
1252 dividend |= (mbedtls_t_udbl) u0;
1253 quotient = dividend / d;
1254 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1255 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1256
1257 if( r != NULL )
Simon Butcher61891752016-01-03 00:24:34 +00001258 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcherea303e32015-11-26 23:43:34 +00001259
1260 return (mbedtls_mpi_uint) quotient;
1261#else
Simon Butcherea303e32015-11-26 23:43:34 +00001262
1263 /*
1264 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1265 * Vol. 2 - Seminumerical Algorithms, Knuth
1266 */
1267
1268 /*
1269 * Normalize the divisor, d, and dividend, u0, u1
1270 */
1271 s = mbedtls_clz( d );
1272 d = d << s;
1273
1274 u1 = u1 << s;
Simon Butcher61891752016-01-03 00:24:34 +00001275 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcherea303e32015-11-26 23:43:34 +00001276 u0 = u0 << s;
1277
1278 d1 = d >> biH;
Simon Butcher61891752016-01-03 00:24:34 +00001279 d0 = d & uint_halfword_mask;
Simon Butcherea303e32015-11-26 23:43:34 +00001280
1281 u0_msw = u0 >> biH;
Simon Butcher61891752016-01-03 00:24:34 +00001282 u0_lsw = u0 & uint_halfword_mask;
Simon Butcherea303e32015-11-26 23:43:34 +00001283
1284 /*
1285 * Find the first quotient and remainder
1286 */
1287 q1 = u1 / d1;
1288 r0 = u1 - d1 * q1;
1289
1290 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1291 {
1292 q1 -= 1;
1293 r0 += d1;
1294
1295 if ( r0 >= radix ) break;
1296 }
1297
Simon Butcher7ebe2782015-12-28 00:05:30 +00001298 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcherea303e32015-11-26 23:43:34 +00001299 q0 = rAX / d1;
1300 r0 = rAX - q0 * d1;
1301
1302 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1303 {
1304 q0 -= 1;
1305 r0 += d1;
1306
1307 if ( r0 >= radix ) break;
1308 }
1309
1310 if (r != NULL)
Simon Butcher7ebe2782015-12-28 00:05:30 +00001311 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcherea303e32015-11-26 23:43:34 +00001312
1313 quotient = q1 * radix + q0;
1314
1315 return quotient;
1316#endif
1317}
1318
1319/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001320 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001321 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001322int 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 +00001323{
Paul Bakker23986e52011-04-24 08:57:21 +00001324 int ret;
1325 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001326 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001327
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001328 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1329 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001330
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001331 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1332 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001334 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001335 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1337 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001338 return( 0 );
1339 }
1340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001341 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1342 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001343 X.s = Y.s = 1;
1344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001345 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1346 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1347 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1348 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001349
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001350 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001351 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001352 {
1353 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001354 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1355 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001356 }
1357 else k = 0;
1358
1359 n = X.n - 1;
1360 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001361 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001362
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001363 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001364 {
1365 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001367 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001368 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001369
1370 for( i = n; i > t ; i-- )
1371 {
1372 if( X.p[i] >= Y.p[t] )
1373 Z.p[i - t - 1] = ~0;
1374 else
1375 {
Simon Butcherea303e32015-11-26 23:43:34 +00001376 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1377 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001378 }
1379
1380 Z.p[i - t - 1]++;
1381 do
1382 {
1383 Z.p[i - t - 1]--;
1384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001385 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001386 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001387 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001388 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001391 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1392 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001393 T2.p[2] = X.p[i];
1394 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001395 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001397 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1398 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1399 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001400
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001401 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001402 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1404 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1405 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001406 Z.p[i - t - 1]--;
1407 }
1408 }
1409
1410 if( Q != NULL )
1411 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001412 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001413 Q->s = A->s * B->s;
1414 }
1415
1416 if( R != NULL )
1417 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001418 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001419 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001420 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001421
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001422 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001423 R->s = 1;
1424 }
1425
1426cleanup:
1427
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001428 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1429 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001430
1431 return( ret );
1432}
1433
1434/*
1435 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001436 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001437int 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 +00001438{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001439 mbedtls_mpi _B;
1440 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001441
1442 p[0] = ( b < 0 ) ? -b : b;
1443 _B.s = ( b < 0 ) ? -1 : 1;
1444 _B.n = 1;
1445 _B.p = p;
1446
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001447 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001448}
1449
1450/*
1451 * Modulo: R = A mod B
1452 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001453int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001454{
1455 int ret;
1456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001457 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1458 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001460 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001461
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001462 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1463 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001465 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1466 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001467
1468cleanup:
1469
1470 return( ret );
1471}
1472
1473/*
1474 * Modulo: r = A mod b
1475 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001476int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001477{
Paul Bakker23986e52011-04-24 08:57:21 +00001478 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001479 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001480
1481 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001482 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001483
1484 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001485 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001486
1487 /*
1488 * handle trivial cases
1489 */
1490 if( b == 1 )
1491 {
1492 *r = 0;
1493 return( 0 );
1494 }
1495
1496 if( b == 2 )
1497 {
1498 *r = A->p[0] & 1;
1499 return( 0 );
1500 }
1501
1502 /*
1503 * general case
1504 */
Paul Bakker23986e52011-04-24 08:57:21 +00001505 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001506 {
Paul Bakker23986e52011-04-24 08:57:21 +00001507 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001508 y = ( y << biH ) | ( x >> biH );
1509 z = y / b;
1510 y -= z * b;
1511
1512 x <<= biH;
1513 y = ( y << biH ) | ( x >> biH );
1514 z = y / b;
1515 y -= z * b;
1516 }
1517
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001518 /*
1519 * If A is negative, then the current y represents a negative value.
1520 * Flipping it to the positive side.
1521 */
1522 if( A->s < 0 && y != 0 )
1523 y = b - y;
1524
Paul Bakker5121ce52009-01-03 21:22:43 +00001525 *r = y;
1526
1527 return( 0 );
1528}
1529
1530/*
1531 * Fast Montgomery initialization (thanks to Tom St Denis)
1532 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001533static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001534{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001535 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001536 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001537
1538 x = m0;
1539 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001540
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001541 for( i = biL; i >= 8; i /= 2 )
1542 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001543
1544 *mm = ~x + 1;
1545}
1546
1547/*
1548 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1549 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001550static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1551 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001552{
Paul Bakker23986e52011-04-24 08:57:21 +00001553 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001554 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001555
1556 memset( T->p, 0, T->n * ciL );
1557
1558 d = T->p;
1559 n = N->n;
1560 m = ( B->n < n ) ? B->n : n;
1561
1562 for( i = 0; i < n; i++ )
1563 {
1564 /*
1565 * T = (T + u0*B + u1*N) / 2^biL
1566 */
1567 u0 = A->p[i];
1568 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1569
1570 mpi_mul_hlp( m, B->p, d, u0 );
1571 mpi_mul_hlp( n, N->p, d, u1 );
1572
1573 *d++ = u0; d[n + 1] = 0;
1574 }
1575
Paul Bakker66d5d072014-06-17 16:39:18 +02001576 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001578 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001579 mpi_sub_hlp( n, N->p, A->p );
1580 else
1581 /* prevent timing attacks */
1582 mpi_sub_hlp( n, A->p, T->p );
1583}
1584
1585/*
1586 * Montgomery reduction: A = A * R^-1 mod N
1587 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001588static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001589{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001590 mbedtls_mpi_uint z = 1;
1591 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001592
Paul Bakker8ddb6452013-02-27 14:56:33 +01001593 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001594 U.p = &z;
1595
1596 mpi_montmul( A, &U, N, mm, T );
1597}
1598
1599/*
1600 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1601 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001602int 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 +00001603{
Paul Bakker23986e52011-04-24 08:57:21 +00001604 int ret;
1605 size_t wbits, wsize, one = 1;
1606 size_t i, j, nblimbs;
1607 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001608 mbedtls_mpi_uint ei, mm, state;
1609 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001610 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001612 if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
1613 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001615 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1616 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001617
1618 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001619 * Init temps and window size
1620 */
1621 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001622 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1623 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001624 memset( W, 0, sizeof( W ) );
1625
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001626 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001627
1628 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1629 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1630
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001631 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1632 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001633
Paul Bakker5121ce52009-01-03 21:22:43 +00001634 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001635 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1636 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1637 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001638
1639 /*
Paul Bakker50546922012-05-19 08:40:49 +00001640 * Compensate for negative A (and correct at the end)
1641 */
1642 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001643 if( neg )
1644 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001645 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001646 Apos.s = 1;
1647 A = &Apos;
1648 }
1649
1650 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001651 * If 1st call, pre-compute R^2 mod N
1652 */
1653 if( _RR == NULL || _RR->p == NULL )
1654 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001655 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1656 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1657 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001658
1659 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001660 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001661 }
1662 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001663 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001664
1665 /*
1666 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1667 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001668 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1669 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001670 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001672
1673 mpi_montmul( &W[1], &RR, N, mm, &T );
1674
1675 /*
1676 * X = R^2 * R^-1 mod N = R mod N
1677 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001678 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001679 mpi_montred( X, N, mm, &T );
1680
1681 if( wsize > 1 )
1682 {
1683 /*
1684 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1685 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001686 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001687
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1689 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001690
1691 for( i = 0; i < wsize - 1; i++ )
1692 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001693
Paul Bakker5121ce52009-01-03 21:22:43 +00001694 /*
1695 * W[i] = W[i - 1] * W[1]
1696 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001697 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001698 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001699 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1700 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001701
1702 mpi_montmul( &W[i], &W[1], N, mm, &T );
1703 }
1704 }
1705
1706 nblimbs = E->n;
1707 bufsize = 0;
1708 nbits = 0;
1709 wbits = 0;
1710 state = 0;
1711
1712 while( 1 )
1713 {
1714 if( bufsize == 0 )
1715 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001716 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001717 break;
1718
Paul Bakker0d7702c2013-10-29 16:18:35 +01001719 nblimbs--;
1720
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001721 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001722 }
1723
1724 bufsize--;
1725
1726 ei = (E->p[nblimbs] >> bufsize) & 1;
1727
1728 /*
1729 * skip leading 0s
1730 */
1731 if( ei == 0 && state == 0 )
1732 continue;
1733
1734 if( ei == 0 && state == 1 )
1735 {
1736 /*
1737 * out of window, square X
1738 */
1739 mpi_montmul( X, X, N, mm, &T );
1740 continue;
1741 }
1742
1743 /*
1744 * add ei to current window
1745 */
1746 state = 2;
1747
1748 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001749 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001750
1751 if( nbits == wsize )
1752 {
1753 /*
1754 * X = X^wsize R^-1 mod N
1755 */
1756 for( i = 0; i < wsize; i++ )
1757 mpi_montmul( X, X, N, mm, &T );
1758
1759 /*
1760 * X = X * W[wbits] R^-1 mod N
1761 */
1762 mpi_montmul( X, &W[wbits], N, mm, &T );
1763
1764 state--;
1765 nbits = 0;
1766 wbits = 0;
1767 }
1768 }
1769
1770 /*
1771 * process the remaining bits
1772 */
1773 for( i = 0; i < nbits; i++ )
1774 {
1775 mpi_montmul( X, X, N, mm, &T );
1776
1777 wbits <<= 1;
1778
Paul Bakker66d5d072014-06-17 16:39:18 +02001779 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001780 mpi_montmul( X, &W[1], N, mm, &T );
1781 }
1782
1783 /*
1784 * X = A^E * R * R^-1 mod N = A^E mod N
1785 */
1786 mpi_montred( X, N, mm, &T );
1787
Hanno Becker2a8d6552017-04-18 09:07:45 +01001788 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001789 {
1790 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001791 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001792 }
1793
Paul Bakker5121ce52009-01-03 21:22:43 +00001794cleanup:
1795
Paul Bakker66d5d072014-06-17 16:39:18 +02001796 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001797 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001798
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001799 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001800
Paul Bakker75a28602014-03-31 12:08:17 +02001801 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001802 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001803
1804 return( ret );
1805}
1806
Paul Bakker5121ce52009-01-03 21:22:43 +00001807/*
1808 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1809 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001810int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001811{
Paul Bakker23986e52011-04-24 08:57:21 +00001812 int ret;
1813 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001814 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001815
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001817
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001818 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1819 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001820
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001821 lz = mbedtls_mpi_lsb( &TA );
1822 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001823
Paul Bakker66d5d072014-06-17 16:39:18 +02001824 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001825 lz = lzt;
1826
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001827 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1828 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001829
Paul Bakker5121ce52009-01-03 21:22:43 +00001830 TA.s = TB.s = 1;
1831
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001832 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001833 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001834 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1835 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001836
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001837 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001838 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001839 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1840 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001841 }
1842 else
1843 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1845 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846 }
1847 }
1848
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001849 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1850 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001851
1852cleanup:
1853
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001854 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001855
1856 return( ret );
1857}
1858
Paul Bakker33dc46b2014-04-30 16:11:39 +02001859/*
1860 * Fill X with size bytes of random.
1861 *
1862 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001863 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001864 * deterministic, eg for tests).
1865 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001866int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001867 int (*f_rng)(void *, unsigned char *, size_t),
1868 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001869{
Paul Bakker23986e52011-04-24 08:57:21 +00001870 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001871 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001872
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001873 if( size > MBEDTLS_MPI_MAX_SIZE )
1874 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001875
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001876 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1877 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001878
1879cleanup:
Andres Amaya Garcia64f0e092017-06-26 11:20:02 +01001880 mbedtls_zeroize( buf, sizeof( buf ) );
1881
Paul Bakker287781a2011-03-26 13:18:49 +00001882 return( ret );
1883}
1884
Paul Bakker5121ce52009-01-03 21:22:43 +00001885/*
1886 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1887 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001888int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001889{
1890 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001891 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001892
Hanno Becker2938ccb2017-04-18 15:49:39 +01001893 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001895
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001896 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1897 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1898 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001899
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001900 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001901
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001902 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001903 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001904 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001905 goto cleanup;
1906 }
1907
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001908 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1909 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1910 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1911 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001912
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001913 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1914 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1915 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1916 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001917
1918 do
1919 {
1920 while( ( TU.p[0] & 1 ) == 0 )
1921 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001922 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001923
1924 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1925 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001926 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1927 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001928 }
1929
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001930 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1931 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001932 }
1933
1934 while( ( TV.p[0] & 1 ) == 0 )
1935 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001936 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001937
1938 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1939 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001940 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1941 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001942 }
1943
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001944 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1945 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001946 }
1947
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001948 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001949 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001950 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1951 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1952 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001953 }
1954 else
1955 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001956 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1957 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1958 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001959 }
1960 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001961 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001962
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1964 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001965
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001966 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1967 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001968
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001969 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001970
1971cleanup:
1972
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001973 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1974 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1975 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001976
1977 return( ret );
1978}
1979
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001980#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001981
Paul Bakker5121ce52009-01-03 21:22:43 +00001982static const int small_prime[] =
1983{
1984 3, 5, 7, 11, 13, 17, 19, 23,
1985 29, 31, 37, 41, 43, 47, 53, 59,
1986 61, 67, 71, 73, 79, 83, 89, 97,
1987 101, 103, 107, 109, 113, 127, 131, 137,
1988 139, 149, 151, 157, 163, 167, 173, 179,
1989 181, 191, 193, 197, 199, 211, 223, 227,
1990 229, 233, 239, 241, 251, 257, 263, 269,
1991 271, 277, 281, 283, 293, 307, 311, 313,
1992 317, 331, 337, 347, 349, 353, 359, 367,
1993 373, 379, 383, 389, 397, 401, 409, 419,
1994 421, 431, 433, 439, 443, 449, 457, 461,
1995 463, 467, 479, 487, 491, 499, 503, 509,
1996 521, 523, 541, 547, 557, 563, 569, 571,
1997 577, 587, 593, 599, 601, 607, 613, 617,
1998 619, 631, 641, 643, 647, 653, 659, 661,
1999 673, 677, 683, 691, 701, 709, 719, 727,
2000 733, 739, 743, 751, 757, 761, 769, 773,
2001 787, 797, 809, 811, 821, 823, 827, 829,
2002 839, 853, 857, 859, 863, 877, 881, 883,
2003 887, 907, 911, 919, 929, 937, 941, 947,
2004 953, 967, 971, 977, 983, 991, 997, -103
2005};
2006
2007/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002008 * Small divisors test (X must be positive)
2009 *
2010 * Return values:
2011 * 0: no small factor (possible prime, more tests needed)
2012 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002013 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002014 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002015 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002017{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002018 int ret = 0;
2019 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002020 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002021
Paul Bakker5121ce52009-01-03 21:22:43 +00002022 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002024
2025 for( i = 0; small_prime[i] > 0; i++ )
2026 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002027 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002028 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002029
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002030 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002031
2032 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002033 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002034 }
2035
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002036cleanup:
2037 return( ret );
2038}
2039
2040/*
2041 * Miller-Rabin pseudo-primality test (HAC 4.24)
2042 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002043static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002044 int (*f_rng)(void *, unsigned char *, size_t),
2045 void *p_rng )
2046{
Pascal Junodb99183d2015-03-11 16:49:45 +01002047 int ret, count;
2048 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002050
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002051 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2052 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002053
Paul Bakker5121ce52009-01-03 21:22:43 +00002054 /*
2055 * W = |X| - 1
2056 * R = W >> lsb( W )
2057 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2059 s = mbedtls_mpi_lsb( &W );
2060 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2061 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002062
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002063 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002064 /*
2065 * HAC, table 4.4
2066 */
2067 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2068 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2069 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2070
2071 for( i = 0; i < n; i++ )
2072 {
2073 /*
2074 * pick a random A, 1 < A < |X| - 1
2075 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002077
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002078 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00002079 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002080 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002081 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00002082 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002083 A.p[0] |= 3;
2084
Pascal Junodb99183d2015-03-11 16:49:45 +01002085 count = 0;
2086 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002087 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002088
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002089 j = mbedtls_mpi_bitlen( &A );
2090 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002091 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002092 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002093 }
2094
2095 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002096 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002097 }
2098
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002099 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2100 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002101
2102 /*
2103 * A = A^R mod |X|
2104 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002105 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002107 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2108 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002109 continue;
2110
2111 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002112 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002113 {
2114 /*
2115 * A = A * A mod |X|
2116 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002117 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2118 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002120 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002121 break;
2122
2123 j++;
2124 }
2125
2126 /*
2127 * not prime if A != |X| - 1 or A == 1
2128 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002129 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2130 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002131 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002132 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002133 break;
2134 }
2135 }
2136
2137cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002138 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2139 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002140
2141 return( ret );
2142}
2143
2144/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002145 * Pseudo-primality test: small factors, then Miller-Rabin
2146 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002147int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002148 int (*f_rng)(void *, unsigned char *, size_t),
2149 void *p_rng )
2150{
2151 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002152 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002153
2154 XX.s = 1;
2155 XX.n = X->n;
2156 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002157
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002158 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2159 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2160 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002161
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002162 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002163 return( 0 );
2164
2165 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2166 {
2167 if( ret == 1 )
2168 return( 0 );
2169
2170 return( ret );
2171 }
2172
2173 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2174}
2175
2176/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002177 * Prime number generation
2178 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002179int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002180 int (*f_rng)(void *, unsigned char *, size_t),
2181 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002182{
Paul Bakker23986e52011-04-24 08:57:21 +00002183 int ret;
2184 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002185 mbedtls_mpi_uint r;
2186 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002187
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2189 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002190
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002191 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002192
2193 n = BITS_TO_LIMBS( nbits );
2194
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002195 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002196
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002197 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002198 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002199
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002200 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002201
2202 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002203
2204 if( dh_flag == 0 )
2205 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002207 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002208 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002209 goto cleanup;
2210
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002211 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002212 }
2213 }
2214 else
2215 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002216 /*
2217 * An necessary condition for Y and X = 2Y + 1 to be prime
2218 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2219 * Make sure it is satisfied, while keeping X = 3 mod 4
2220 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002221
2222 X->p[0] |= 2;
2223
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002224 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002225 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002226 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002227 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002228 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002229
2230 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002231 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2232 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002233
2234 while( 1 )
2235 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002236 /*
2237 * First, check small factors for X and Y
2238 * before doing Miller-Rabin on any of them
2239 */
2240 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2241 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2242 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2243 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002244 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002245 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002246 }
2247
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002248 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002249 goto cleanup;
2250
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002251 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002252 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002253 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2254 * so up Y by 6 and X by 12.
2255 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002256 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2257 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002258 }
2259 }
2260
2261cleanup:
2262
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002263 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002264
2265 return( ret );
2266}
2267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002268#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002269
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002270#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002271
Paul Bakker23986e52011-04-24 08:57:21 +00002272#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002273
2274static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2275{
2276 { 693, 609, 21 },
2277 { 1764, 868, 28 },
2278 { 768454923, 542167814, 1 }
2279};
2280
Paul Bakker5121ce52009-01-03 21:22:43 +00002281/*
2282 * Checkup routine
2283 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002284int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002285{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002286 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002287 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002288
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002289 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2290 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002291
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002292 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002293 "EFE021C2645FD1DC586E69184AF4A31E" \
2294 "D5F53E93B5F123FA41680867BA110131" \
2295 "944FE7952E2517337780CB0DB80E61AA" \
2296 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2297
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002298 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002299 "B2E7EFD37075B9F03FF989C7C5051C20" \
2300 "34D2A323810251127E7BF8625A4F49A5" \
2301 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2302 "5B5C25763222FEFCCFC38B832366C29E" ) );
2303
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002304 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002305 "0066A198186C18C10B2F5ED9B522752A" \
2306 "9830B69916E535C8F047518A889A43A5" \
2307 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2308
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002309 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002310
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002311 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002312 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2313 "9E857EA95A03512E2BAE7391688D264A" \
2314 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2315 "8001B72E848A38CAE1C65F78E56ABDEF" \
2316 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2317 "ECF677152EF804370C1A305CAF3B5BF1" \
2318 "30879B56C61DE584A0F53A2447A51E" ) );
2319
2320 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002321 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002322
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002323 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002324 {
2325 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002326 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002327
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002328 ret = 1;
2329 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002330 }
2331
2332 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002333 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002336
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002337 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002338 "256567336059E52CAE22925474705F39A94" ) );
2339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002340 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002341 "6613F26162223DF488E9CD48CC132C7A" \
2342 "0AC93C701B001B092E4E5B9F73BCD27B" \
2343 "9EE50D0657C77F374E903CDFA4C642" ) );
2344
2345 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002346 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002347
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002348 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2349 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002350 {
2351 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002352 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002353
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002354 ret = 1;
2355 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002356 }
2357
2358 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002361 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002362
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002363 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002364 "36E139AEA55215609D2816998ED020BB" \
2365 "BD96C37890F65171D948E9BC7CBAA4D9" \
2366 "325D24D6A3C12710F10A09FA08AB87" ) );
2367
2368 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002369 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002370
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002371 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002372 {
2373 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002374 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002375
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002376 ret = 1;
2377 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002378 }
2379
2380 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002381 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002386 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2387 "C3DBA76456363A10869622EAC2DD84EC" \
2388 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2389
2390 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002391 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002393 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002394 {
2395 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002397
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002398 ret = 1;
2399 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002400 }
2401
2402 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002403 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002404
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002405 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002406 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002407
Paul Bakker66d5d072014-06-17 16:39:18 +02002408 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002409 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002410 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2411 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002413 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002414
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002415 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002416 {
2417 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002418 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002419
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002420 ret = 1;
2421 goto cleanup;
2422 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002423 }
2424
2425 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002426 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002427
Paul Bakker5121ce52009-01-03 21:22:43 +00002428cleanup:
2429
2430 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002431 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002432
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002433 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2434 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002435
2436 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002437 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002438
2439 return( ret );
2440}
2441
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002442#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002443
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002444#endif /* MBEDTLS_BIGNUM_C */