blob: f0fabd6984346d68a0d45ff2b8b9d6a28a0cc9f6 [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
Paul Bakker5121ce52009-01-03 21:22:43 +0000619 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
620 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
621
622 p = s + slen;
623 while( --p >= s )
624 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:
1880 return( ret );
1881}
1882
Paul Bakker5121ce52009-01-03 21:22:43 +00001883/*
1884 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1885 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001886int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001887{
1888 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001889 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001890
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001891 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 )
1892 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001893
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1895 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1896 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001897
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001898 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001899
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001900 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001901 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001902 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001903 goto cleanup;
1904 }
1905
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001906 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1907 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1908 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1909 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001910
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001911 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1912 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1913 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1914 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001915
1916 do
1917 {
1918 while( ( TU.p[0] & 1 ) == 0 )
1919 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001920 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001921
1922 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1923 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001924 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1925 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001926 }
1927
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001928 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1929 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001930 }
1931
1932 while( ( TV.p[0] & 1 ) == 0 )
1933 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001934 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001935
1936 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1937 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001938 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1939 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001940 }
1941
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001942 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1943 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001944 }
1945
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001946 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001947 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001948 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1949 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1950 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001951 }
1952 else
1953 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001954 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1955 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1956 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001957 }
1958 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001960
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001961 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1962 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001963
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001964 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1965 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001966
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001967 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001968
1969cleanup:
1970
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001971 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1972 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1973 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001974
1975 return( ret );
1976}
1977
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001978#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001979
Paul Bakker5121ce52009-01-03 21:22:43 +00001980static const int small_prime[] =
1981{
1982 3, 5, 7, 11, 13, 17, 19, 23,
1983 29, 31, 37, 41, 43, 47, 53, 59,
1984 61, 67, 71, 73, 79, 83, 89, 97,
1985 101, 103, 107, 109, 113, 127, 131, 137,
1986 139, 149, 151, 157, 163, 167, 173, 179,
1987 181, 191, 193, 197, 199, 211, 223, 227,
1988 229, 233, 239, 241, 251, 257, 263, 269,
1989 271, 277, 281, 283, 293, 307, 311, 313,
1990 317, 331, 337, 347, 349, 353, 359, 367,
1991 373, 379, 383, 389, 397, 401, 409, 419,
1992 421, 431, 433, 439, 443, 449, 457, 461,
1993 463, 467, 479, 487, 491, 499, 503, 509,
1994 521, 523, 541, 547, 557, 563, 569, 571,
1995 577, 587, 593, 599, 601, 607, 613, 617,
1996 619, 631, 641, 643, 647, 653, 659, 661,
1997 673, 677, 683, 691, 701, 709, 719, 727,
1998 733, 739, 743, 751, 757, 761, 769, 773,
1999 787, 797, 809, 811, 821, 823, 827, 829,
2000 839, 853, 857, 859, 863, 877, 881, 883,
2001 887, 907, 911, 919, 929, 937, 941, 947,
2002 953, 967, 971, 977, 983, 991, 997, -103
2003};
2004
2005/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002006 * Small divisors test (X must be positive)
2007 *
2008 * Return values:
2009 * 0: no small factor (possible prime, more tests needed)
2010 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002011 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002012 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002013 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002014static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002015{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002016 int ret = 0;
2017 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002018 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002019
Paul Bakker5121ce52009-01-03 21:22:43 +00002020 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002021 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
2023 for( i = 0; small_prime[i] > 0; i++ )
2024 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002025 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002026 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002027
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002028 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002029
2030 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002031 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002032 }
2033
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002034cleanup:
2035 return( ret );
2036}
2037
2038/*
2039 * Miller-Rabin pseudo-primality test (HAC 4.24)
2040 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002041static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002042 int (*f_rng)(void *, unsigned char *, size_t),
2043 void *p_rng )
2044{
Pascal Junodb99183d2015-03-11 16:49:45 +01002045 int ret, count;
2046 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002047 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002048
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2050 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002051
Paul Bakker5121ce52009-01-03 21:22:43 +00002052 /*
2053 * W = |X| - 1
2054 * R = W >> lsb( W )
2055 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002056 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2057 s = mbedtls_mpi_lsb( &W );
2058 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2059 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002060
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002061 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002062 /*
2063 * HAC, table 4.4
2064 */
2065 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2066 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2067 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2068
2069 for( i = 0; i < n; i++ )
2070 {
2071 /*
2072 * pick a random A, 1 < A < |X| - 1
2073 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002074 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002075
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00002077 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002078 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002079 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00002080 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002081 A.p[0] |= 3;
2082
Pascal Junodb99183d2015-03-11 16:49:45 +01002083 count = 0;
2084 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002085 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002086
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002087 j = mbedtls_mpi_bitlen( &A );
2088 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002089 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002090 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002091 }
2092
2093 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002094 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002095 }
2096
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002097 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2098 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002099
2100 /*
2101 * A = A^R mod |X|
2102 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002103 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002104
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002105 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2106 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002107 continue;
2108
2109 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002110 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002111 {
2112 /*
2113 * A = A * A mod |X|
2114 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002115 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2116 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002117
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002118 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002119 break;
2120
2121 j++;
2122 }
2123
2124 /*
2125 * not prime if A != |X| - 1 or A == 1
2126 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002127 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2128 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002129 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002130 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002131 break;
2132 }
2133 }
2134
2135cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002136 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2137 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002138
2139 return( ret );
2140}
2141
2142/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002143 * Pseudo-primality test: small factors, then Miller-Rabin
2144 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002146 int (*f_rng)(void *, unsigned char *, size_t),
2147 void *p_rng )
2148{
2149 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002150 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002151
2152 XX.s = 1;
2153 XX.n = X->n;
2154 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002155
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002156 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2157 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2158 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002161 return( 0 );
2162
2163 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2164 {
2165 if( ret == 1 )
2166 return( 0 );
2167
2168 return( ret );
2169 }
2170
2171 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2172}
2173
2174/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002175 * Prime number generation
2176 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002178 int (*f_rng)(void *, unsigned char *, size_t),
2179 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002180{
Paul Bakker23986e52011-04-24 08:57:21 +00002181 int ret;
2182 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002183 mbedtls_mpi_uint r;
2184 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002185
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002186 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2187 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002189 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002190
2191 n = BITS_TO_LIMBS( nbits );
2192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002193 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002194
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002195 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002196 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002197
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002198 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002199
2200 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002201
2202 if( dh_flag == 0 )
2203 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002204 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002205 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002207 goto cleanup;
2208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002209 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002210 }
2211 }
2212 else
2213 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002214 /*
2215 * An necessary condition for Y and X = 2Y + 1 to be prime
2216 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2217 * Make sure it is satisfied, while keeping X = 3 mod 4
2218 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002219
2220 X->p[0] |= 2;
2221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002222 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002223 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002224 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002225 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002226 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002227
2228 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002229 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2230 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002231
2232 while( 1 )
2233 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002234 /*
2235 * First, check small factors for X and Y
2236 * before doing Miller-Rabin on any of them
2237 */
2238 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2239 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2240 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2241 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002242 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002243 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002244 }
2245
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002246 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002247 goto cleanup;
2248
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002249 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002250 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002251 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2252 * so up Y by 6 and X by 12.
2253 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002254 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2255 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002256 }
2257 }
2258
2259cleanup:
2260
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002261 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002262
2263 return( ret );
2264}
2265
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002266#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002268#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002269
Paul Bakker23986e52011-04-24 08:57:21 +00002270#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002271
2272static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2273{
2274 { 693, 609, 21 },
2275 { 1764, 868, 28 },
2276 { 768454923, 542167814, 1 }
2277};
2278
Paul Bakker5121ce52009-01-03 21:22:43 +00002279/*
2280 * Checkup routine
2281 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002282int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002283{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002284 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002285 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002287 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2288 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002289
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002290 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002291 "EFE021C2645FD1DC586E69184AF4A31E" \
2292 "D5F53E93B5F123FA41680867BA110131" \
2293 "944FE7952E2517337780CB0DB80E61AA" \
2294 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2295
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002296 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002297 "B2E7EFD37075B9F03FF989C7C5051C20" \
2298 "34D2A323810251127E7BF8625A4F49A5" \
2299 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2300 "5B5C25763222FEFCCFC38B832366C29E" ) );
2301
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002302 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002303 "0066A198186C18C10B2F5ED9B522752A" \
2304 "9830B69916E535C8F047518A889A43A5" \
2305 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002308
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002309 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002310 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2311 "9E857EA95A03512E2BAE7391688D264A" \
2312 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2313 "8001B72E848A38CAE1C65F78E56ABDEF" \
2314 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2315 "ECF677152EF804370C1A305CAF3B5BF1" \
2316 "30879B56C61DE584A0F53A2447A51E" ) );
2317
2318 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002319 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002321 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002322 {
2323 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002324 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002325
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002326 ret = 1;
2327 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002328 }
2329
2330 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002331 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002333 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002336 "256567336059E52CAE22925474705F39A94" ) );
2337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002339 "6613F26162223DF488E9CD48CC132C7A" \
2340 "0AC93C701B001B092E4E5B9F73BCD27B" \
2341 "9EE50D0657C77F374E903CDFA4C642" ) );
2342
2343 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002344 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002346 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2347 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002348 {
2349 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002350 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002351
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002352 ret = 1;
2353 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002354 }
2355
2356 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002357 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002358
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002361 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002362 "36E139AEA55215609D2816998ED020BB" \
2363 "BD96C37890F65171D948E9BC7CBAA4D9" \
2364 "325D24D6A3C12710F10A09FA08AB87" ) );
2365
2366 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002369 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002370 {
2371 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002372 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002373
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002374 ret = 1;
2375 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002376 }
2377
2378 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002379 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002381 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002384 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2385 "C3DBA76456363A10869622EAC2DD84EC" \
2386 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2387
2388 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002389 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002390
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002391 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002392 {
2393 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002394 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002395
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002396 ret = 1;
2397 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002398 }
2399
2400 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002401 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002402
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002403 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002404 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002405
Paul Bakker66d5d072014-06-17 16:39:18 +02002406 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002407 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002408 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2409 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002410
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002411 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002413 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002414 {
2415 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002416 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002417
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002418 ret = 1;
2419 goto cleanup;
2420 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002421 }
2422
2423 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002424 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002425
Paul Bakker5121ce52009-01-03 21:22:43 +00002426cleanup:
2427
2428 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002429 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002431 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2432 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002433
2434 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002435 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002436
2437 return( ret );
2438}
2439
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002441
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002442#endif /* MBEDTLS_BIGNUM_C */