blob: 5009a71f57f79b40f32ada1983c4868d25907da5 [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;
537 n += 3;
538
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100539 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000540 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100541 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000543 }
544
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100545 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000547
548 if( X->s == -1 )
549 *p++ = '-';
550
551 if( radix == 16 )
552 {
Paul Bakker23986e52011-04-24 08:57:21 +0000553 int c;
554 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000555
Paul Bakker23986e52011-04-24 08:57:21 +0000556 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000557 {
Paul Bakker23986e52011-04-24 08:57:21 +0000558 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000559 {
Paul Bakker23986e52011-04-24 08:57:21 +0000560 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000561
Paul Bakker6c343d72014-07-10 14:36:19 +0200562 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000563 continue;
564
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000565 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000566 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000567 k = 1;
568 }
569 }
570 }
571 else
572 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000574
575 if( T.s == -1 )
576 T.s = 1;
577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000579 }
580
581 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100582 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000583
584cleanup:
585
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000587
588 return( ret );
589}
590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000592/*
593 * Read X from an opened file
594 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200595int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000596{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000598 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000599 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000600 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000601 * Buffer should have space for (short) label and decimal formatted MPI,
602 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000603 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000605
606 memset( s, 0, sizeof( s ) );
607 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000609
610 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000611 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000613
Paul Bakker5121ce52009-01-03 21:22:43 +0000614 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
615 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
616
617 p = s + slen;
618 while( --p >= s )
619 if( mpi_get_digit( &d, radix, *p ) != 0 )
620 break;
621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000623}
624
625/*
626 * Write X into an opened file (or stdout if fout == NULL)
627 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000629{
Paul Bakker23986e52011-04-24 08:57:21 +0000630 int ret;
631 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000632 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000633 * Buffer should have space for (short) label and decimal formatted MPI,
634 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000635 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200636 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000637
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100638 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000639
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100640 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000641
642 if( p == NULL ) p = "";
643
644 plen = strlen( p );
645 slen = strlen( s );
646 s[slen++] = '\r';
647 s[slen++] = '\n';
648
649 if( fout != NULL )
650 {
651 if( fwrite( p, 1, plen, fout ) != plen ||
652 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000654 }
655 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000657
658cleanup:
659
660 return( ret );
661}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000663
664/*
665 * Import X from unsigned binary data, big endian
666 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000668{
Paul Bakker23986e52011-04-24 08:57:21 +0000669 int ret;
670 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000671
672 for( n = 0; n < buflen; n++ )
673 if( buf[n] != 0 )
674 break;
675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
677 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000678
Paul Bakker23986e52011-04-24 08:57:21 +0000679 for( i = buflen, j = 0; i > n; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000681
682cleanup:
683
684 return( ret );
685}
686
687/*
688 * Export X into unsigned binary data, big endian
689 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000691{
Paul Bakker23986e52011-04-24 08:57:21 +0000692 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000693
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200694 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000695
696 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
699 memset( buf, 0, buflen );
700
701 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
702 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
703
704 return( 0 );
705}
706
707/*
708 * Left-shift: X <<= count
709 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000711{
Paul Bakker23986e52011-04-24 08:57:21 +0000712 int ret;
713 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000715
716 v0 = count / (biL );
717 t1 = count & (biL - 1);
718
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200719 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000720
Paul Bakkerf9688572011-05-05 10:00:45 +0000721 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000723
724 ret = 0;
725
726 /*
727 * shift by count / limb_size
728 */
729 if( v0 > 0 )
730 {
Paul Bakker23986e52011-04-24 08:57:21 +0000731 for( i = X->n; i > v0; i-- )
732 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000733
Paul Bakker23986e52011-04-24 08:57:21 +0000734 for( ; i > 0; i-- )
735 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000736 }
737
738 /*
739 * shift by count % limb_size
740 */
741 if( t1 > 0 )
742 {
743 for( i = v0; i < X->n; i++ )
744 {
745 r1 = X->p[i] >> (biL - t1);
746 X->p[i] <<= t1;
747 X->p[i] |= r0;
748 r0 = r1;
749 }
750 }
751
752cleanup:
753
754 return( ret );
755}
756
757/*
758 * Right-shift: X >>= count
759 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200760int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000761{
Paul Bakker23986e52011-04-24 08:57:21 +0000762 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200763 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000764
765 v0 = count / biL;
766 v1 = count & (biL - 1);
767
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100768 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200769 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100770
Paul Bakker5121ce52009-01-03 21:22:43 +0000771 /*
772 * shift by count / limb_size
773 */
774 if( v0 > 0 )
775 {
776 for( i = 0; i < X->n - v0; i++ )
777 X->p[i] = X->p[i + v0];
778
779 for( ; i < X->n; i++ )
780 X->p[i] = 0;
781 }
782
783 /*
784 * shift by count % limb_size
785 */
786 if( v1 > 0 )
787 {
Paul Bakker23986e52011-04-24 08:57:21 +0000788 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000789 {
Paul Bakker23986e52011-04-24 08:57:21 +0000790 r1 = X->p[i - 1] << (biL - v1);
791 X->p[i - 1] >>= v1;
792 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000793 r0 = r1;
794 }
795 }
796
797 return( 0 );
798}
799
800/*
801 * Compare unsigned values
802 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200803int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000804{
Paul Bakker23986e52011-04-24 08:57:21 +0000805 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000806
Paul Bakker23986e52011-04-24 08:57:21 +0000807 for( i = X->n; i > 0; i-- )
808 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000809 break;
810
Paul Bakker23986e52011-04-24 08:57:21 +0000811 for( j = Y->n; j > 0; j-- )
812 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000813 break;
814
Paul Bakker23986e52011-04-24 08:57:21 +0000815 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000816 return( 0 );
817
818 if( i > j ) return( 1 );
819 if( j > i ) return( -1 );
820
Paul Bakker23986e52011-04-24 08:57:21 +0000821 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000822 {
Paul Bakker23986e52011-04-24 08:57:21 +0000823 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
824 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000825 }
826
827 return( 0 );
828}
829
830/*
831 * Compare signed values
832 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200833int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000834{
Paul Bakker23986e52011-04-24 08:57:21 +0000835 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000836
Paul Bakker23986e52011-04-24 08:57:21 +0000837 for( i = X->n; i > 0; i-- )
838 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000839 break;
840
Paul Bakker23986e52011-04-24 08:57:21 +0000841 for( j = Y->n; j > 0; j-- )
842 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000843 break;
844
Paul Bakker23986e52011-04-24 08:57:21 +0000845 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000846 return( 0 );
847
848 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000849 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000850
851 if( X->s > 0 && Y->s < 0 ) return( 1 );
852 if( Y->s > 0 && X->s < 0 ) return( -1 );
853
Paul Bakker23986e52011-04-24 08:57:21 +0000854 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000855 {
Paul Bakker23986e52011-04-24 08:57:21 +0000856 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
857 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000858 }
859
860 return( 0 );
861}
862
863/*
864 * Compare signed values
865 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200866int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000867{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200868 mbedtls_mpi Y;
869 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000870
871 *p = ( z < 0 ) ? -z : z;
872 Y.s = ( z < 0 ) ? -1 : 1;
873 Y.n = 1;
874 Y.p = p;
875
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200876 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000877}
878
879/*
880 * Unsigned addition: X = |A| + |B| (HAC 14.7)
881 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200882int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000883{
Paul Bakker23986e52011-04-24 08:57:21 +0000884 int ret;
885 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200886 mbedtls_mpi_uint *o, *p, c;
Janos Follatha65477d2015-10-25 14:24:10 +0100887 mbedtls_mpi TB;
Paul Bakker5121ce52009-01-03 21:22:43 +0000888
889 if( X == B )
890 {
Janos Follatha65477d2015-10-25 14:24:10 +0100891 B = A; A = X;
892
Janos Follath5429c0a2015-10-25 12:29:13 +0100893 if( B == A )
894 {
895 // Making a temporary copy instead of shifting by one to deny
896 // the possibility of corresponding side-channel attacks.
Janos Follath5429c0a2015-10-25 12:29:13 +0100897 mbedtls_mpi_init( &TB );
898 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
899
Janos Follatha65477d2015-10-25 14:24:10 +0100900 B = &TB;
Janos Follath5429c0a2015-10-25 12:29:13 +0100901 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000902 }
903
904 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200905 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200906
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000907 /*
908 * X should always be positive as a result of unsigned additions.
909 */
910 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000911
Paul Bakker23986e52011-04-24 08:57:21 +0000912 for( j = B->n; j > 0; j-- )
913 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000914 break;
915
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200916 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000917
918 o = B->p; p = X->p; c = 0;
919
Paul Bakker23986e52011-04-24 08:57:21 +0000920 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000921 {
922 *p += c; c = ( *p < c );
923 *p += *o; c += ( *p < *o );
924 }
925
926 while( c != 0 )
927 {
928 if( i >= X->n )
929 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200930 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000931 p = X->p + i;
932 }
933
Paul Bakker2d319fd2012-09-16 21:34:26 +0000934 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000935 }
936
937cleanup:
Janos Follatha65477d2015-10-25 14:24:10 +0100938 if( &TB == B )
939 {
940 mbedtls_mpi_free( &TB );
941 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000942
943 return( ret );
944}
945
946/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000948 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200949static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000950{
Paul Bakker23986e52011-04-24 08:57:21 +0000951 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200952 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000953
954 for( i = c = 0; i < n; i++, s++, d++ )
955 {
956 z = ( *d < c ); *d -= c;
957 c = ( *d < *s ) + z; *d -= *s;
958 }
959
960 while( c != 0 )
961 {
962 z = ( *d < c ); *d -= c;
963 c = z; i++; d++;
964 }
965}
966
967/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100968 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000969 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200970int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000971{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200972 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000973 int ret;
974 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000975
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200976 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
977 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000978
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200979 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000980
981 if( X == B )
982 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200983 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000984 B = &TB;
985 }
986
987 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200988 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000989
Paul Bakker1ef7a532009-06-20 10:50:55 +0000990 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100991 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000992 */
993 X->s = 1;
994
Paul Bakker5121ce52009-01-03 21:22:43 +0000995 ret = 0;
996
Paul Bakker23986e52011-04-24 08:57:21 +0000997 for( n = B->n; n > 0; n-- )
998 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000999 break;
1000
Paul Bakker23986e52011-04-24 08:57:21 +00001001 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001002
1003cleanup:
1004
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001005 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001006
1007 return( ret );
1008}
1009
1010/*
1011 * Signed addition: X = A + B
1012 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001013int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001014{
1015 int ret, s = A->s;
1016
1017 if( A->s * B->s < 0 )
1018 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001020 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001021 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001022 X->s = s;
1023 }
1024 else
1025 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001026 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001027 X->s = -s;
1028 }
1029 }
1030 else
1031 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001032 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001033 X->s = s;
1034 }
1035
1036cleanup:
1037
1038 return( ret );
1039}
1040
1041/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001042 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001043 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001044int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001045{
1046 int ret, s = A->s;
1047
1048 if( A->s * B->s > 0 )
1049 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001051 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001052 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001053 X->s = s;
1054 }
1055 else
1056 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001057 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001058 X->s = -s;
1059 }
1060 }
1061 else
1062 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001063 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001064 X->s = s;
1065 }
1066
1067cleanup:
1068
1069 return( ret );
1070}
1071
1072/*
1073 * Signed addition: X = A + b
1074 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001075int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001076{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001077 mbedtls_mpi _B;
1078 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001079
1080 p[0] = ( b < 0 ) ? -b : b;
1081 _B.s = ( b < 0 ) ? -1 : 1;
1082 _B.n = 1;
1083 _B.p = p;
1084
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001085 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001086}
1087
1088/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001089 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001090 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001091int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001092{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001093 mbedtls_mpi _B;
1094 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001095
1096 p[0] = ( b < 0 ) ? -b : b;
1097 _B.s = ( b < 0 ) ? -1 : 1;
1098 _B.n = 1;
1099 _B.p = p;
1100
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001101 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001102}
1103
1104/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001105 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001106 */
1107static
1108#if defined(__APPLE__) && defined(__arm__)
1109/*
1110 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1111 * appears to need this to prevent bad ARM code generation at -O3.
1112 */
1113__attribute__ ((noinline))
1114#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115void 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 +00001116{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001117 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001118
1119#if defined(MULADDC_HUIT)
1120 for( ; i >= 8; i -= 8 )
1121 {
1122 MULADDC_INIT
1123 MULADDC_HUIT
1124 MULADDC_STOP
1125 }
1126
1127 for( ; i > 0; i-- )
1128 {
1129 MULADDC_INIT
1130 MULADDC_CORE
1131 MULADDC_STOP
1132 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001133#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001134 for( ; i >= 16; i -= 16 )
1135 {
1136 MULADDC_INIT
1137 MULADDC_CORE MULADDC_CORE
1138 MULADDC_CORE MULADDC_CORE
1139 MULADDC_CORE MULADDC_CORE
1140 MULADDC_CORE MULADDC_CORE
1141
1142 MULADDC_CORE MULADDC_CORE
1143 MULADDC_CORE MULADDC_CORE
1144 MULADDC_CORE MULADDC_CORE
1145 MULADDC_CORE MULADDC_CORE
1146 MULADDC_STOP
1147 }
1148
1149 for( ; i >= 8; i -= 8 )
1150 {
1151 MULADDC_INIT
1152 MULADDC_CORE MULADDC_CORE
1153 MULADDC_CORE MULADDC_CORE
1154
1155 MULADDC_CORE MULADDC_CORE
1156 MULADDC_CORE MULADDC_CORE
1157 MULADDC_STOP
1158 }
1159
1160 for( ; i > 0; i-- )
1161 {
1162 MULADDC_INIT
1163 MULADDC_CORE
1164 MULADDC_STOP
1165 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001166#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001167
1168 t++;
1169
1170 do {
1171 *d += c; c = ( *d < c ); d++;
1172 }
1173 while( c != 0 );
1174}
1175
1176/*
1177 * Baseline multiplication: X = A * B (HAC 14.12)
1178 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001179int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001180{
Paul Bakker23986e52011-04-24 08:57:21 +00001181 int ret;
1182 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001183 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001185 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001186
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001187 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1188 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001189
Paul Bakker23986e52011-04-24 08:57:21 +00001190 for( i = A->n; i > 0; i-- )
1191 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001192 break;
1193
Paul Bakker23986e52011-04-24 08:57:21 +00001194 for( j = B->n; j > 0; j-- )
1195 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001196 break;
1197
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001198 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1199 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001200
Paul Bakker23986e52011-04-24 08:57:21 +00001201 for( i++; j > 0; j-- )
1202 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001203
1204 X->s = A->s * B->s;
1205
1206cleanup:
1207
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001208 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001209
1210 return( ret );
1211}
1212
1213/*
1214 * Baseline multiplication: X = A * b
1215 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001216int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001217{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001218 mbedtls_mpi _B;
1219 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001220
1221 _B.s = 1;
1222 _B.n = 1;
1223 _B.p = p;
1224 p[0] = b;
1225
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001226 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001227}
1228
1229/*
Simon Butcher7ebe2782015-12-28 00:05:30 +00001230 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1231 * mbedtls_mpi_uint divisor, d
Simon Butcherea303e32015-11-26 23:43:34 +00001232 */
Simon Butcher7ebe2782015-12-28 00:05:30 +00001233static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1234 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcherea303e32015-11-26 23:43:34 +00001235{
Manuel Pégourié-Gonnard5a8396e2015-12-01 10:27:00 +01001236#if defined(MBEDTLS_HAVE_UDBL)
1237 mbedtls_t_udbl dividend, quotient;
Simon Butcher7ebe2782015-12-28 00:05:30 +00001238#else
Simon Butcher61891752016-01-03 00:24:34 +00001239 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1240 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcher7ebe2782015-12-28 00:05:30 +00001241 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1242 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher61891752016-01-03 00:24:34 +00001243 size_t s;
Manuel Pégourié-Gonnard5a8396e2015-12-01 10:27:00 +01001244#endif
1245
Simon Butcherea303e32015-11-26 23:43:34 +00001246 /*
1247 * Check for overflow
1248 */
Simon Butcher7ebe2782015-12-28 00:05:30 +00001249 if( 0 == d || u1 >= d )
Simon Butcherea303e32015-11-26 23:43:34 +00001250 {
Simon Butcher7ebe2782015-12-28 00:05:30 +00001251 if (r != NULL) *r = ~0;
Simon Butcherea303e32015-11-26 23:43:34 +00001252
Simon Butcher7ebe2782015-12-28 00:05:30 +00001253 return ( ~0 );
Simon Butcherea303e32015-11-26 23:43:34 +00001254 }
1255
1256#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcherea303e32015-11-26 23:43:34 +00001257 dividend = (mbedtls_t_udbl) u1 << biL;
1258 dividend |= (mbedtls_t_udbl) u0;
1259 quotient = dividend / d;
1260 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1261 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1262
1263 if( r != NULL )
Simon Butcher61891752016-01-03 00:24:34 +00001264 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcherea303e32015-11-26 23:43:34 +00001265
1266 return (mbedtls_mpi_uint) quotient;
1267#else
Simon Butcherea303e32015-11-26 23:43:34 +00001268
1269 /*
1270 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1271 * Vol. 2 - Seminumerical Algorithms, Knuth
1272 */
1273
1274 /*
1275 * Normalize the divisor, d, and dividend, u0, u1
1276 */
1277 s = mbedtls_clz( d );
1278 d = d << s;
1279
1280 u1 = u1 << s;
Simon Butcher61891752016-01-03 00:24:34 +00001281 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcherea303e32015-11-26 23:43:34 +00001282 u0 = u0 << s;
1283
1284 d1 = d >> biH;
Simon Butcher61891752016-01-03 00:24:34 +00001285 d0 = d & uint_halfword_mask;
Simon Butcherea303e32015-11-26 23:43:34 +00001286
1287 u0_msw = u0 >> biH;
Simon Butcher61891752016-01-03 00:24:34 +00001288 u0_lsw = u0 & uint_halfword_mask;
Simon Butcherea303e32015-11-26 23:43:34 +00001289
1290 /*
1291 * Find the first quotient and remainder
1292 */
1293 q1 = u1 / d1;
1294 r0 = u1 - d1 * q1;
1295
1296 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1297 {
1298 q1 -= 1;
1299 r0 += d1;
1300
1301 if ( r0 >= radix ) break;
1302 }
1303
Simon Butcher7ebe2782015-12-28 00:05:30 +00001304 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcherea303e32015-11-26 23:43:34 +00001305 q0 = rAX / d1;
1306 r0 = rAX - q0 * d1;
1307
1308 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1309 {
1310 q0 -= 1;
1311 r0 += d1;
1312
1313 if ( r0 >= radix ) break;
1314 }
1315
1316 if (r != NULL)
Simon Butcher7ebe2782015-12-28 00:05:30 +00001317 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcherea303e32015-11-26 23:43:34 +00001318
1319 quotient = q1 * radix + q0;
1320
1321 return quotient;
1322#endif
1323}
1324
1325/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001326 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001327 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001328int 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 +00001329{
Paul Bakker23986e52011-04-24 08:57:21 +00001330 int ret;
1331 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001334 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1335 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001336
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001337 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1338 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001340 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001341 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001342 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1343 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001344 return( 0 );
1345 }
1346
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001347 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1348 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001349 X.s = Y.s = 1;
1350
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001351 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1352 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1353 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1354 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001355
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001356 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001357 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001358 {
1359 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001360 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1361 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001362 }
1363 else k = 0;
1364
1365 n = X.n - 1;
1366 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001367 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001369 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001370 {
1371 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001373 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001374 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001375
1376 for( i = n; i > t ; i-- )
1377 {
1378 if( X.p[i] >= Y.p[t] )
1379 Z.p[i - t - 1] = ~0;
1380 else
1381 {
Simon Butcherea303e32015-11-26 23:43:34 +00001382 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1383 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001384 }
1385
1386 Z.p[i - t - 1]++;
1387 do
1388 {
1389 Z.p[i - t - 1]--;
1390
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001392 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001393 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001394 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001396 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001397 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1398 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001399 T2.p[2] = X.p[i];
1400 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001401 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001402
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1404 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1405 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001406
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001407 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001408 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001409 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1410 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1411 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001412 Z.p[i - t - 1]--;
1413 }
1414 }
1415
1416 if( Q != NULL )
1417 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001418 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001419 Q->s = A->s * B->s;
1420 }
1421
1422 if( R != NULL )
1423 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001424 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001425 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001426 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001427
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001428 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001429 R->s = 1;
1430 }
1431
1432cleanup:
1433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001434 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1435 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001436
1437 return( ret );
1438}
1439
1440/*
1441 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001442 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001443int 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 +00001444{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001445 mbedtls_mpi _B;
1446 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001447
1448 p[0] = ( b < 0 ) ? -b : b;
1449 _B.s = ( b < 0 ) ? -1 : 1;
1450 _B.n = 1;
1451 _B.p = p;
1452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001453 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001454}
1455
1456/*
1457 * Modulo: R = A mod B
1458 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001459int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001460{
1461 int ret;
1462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001463 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1464 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001468 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1469 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1472 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001473
1474cleanup:
1475
1476 return( ret );
1477}
1478
1479/*
1480 * Modulo: r = A mod b
1481 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001482int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001483{
Paul Bakker23986e52011-04-24 08:57:21 +00001484 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001485 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001486
1487 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001488 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001489
1490 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001491 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001492
1493 /*
1494 * handle trivial cases
1495 */
1496 if( b == 1 )
1497 {
1498 *r = 0;
1499 return( 0 );
1500 }
1501
1502 if( b == 2 )
1503 {
1504 *r = A->p[0] & 1;
1505 return( 0 );
1506 }
1507
1508 /*
1509 * general case
1510 */
Paul Bakker23986e52011-04-24 08:57:21 +00001511 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001512 {
Paul Bakker23986e52011-04-24 08:57:21 +00001513 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001514 y = ( y << biH ) | ( x >> biH );
1515 z = y / b;
1516 y -= z * b;
1517
1518 x <<= biH;
1519 y = ( y << biH ) | ( x >> biH );
1520 z = y / b;
1521 y -= z * b;
1522 }
1523
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001524 /*
1525 * If A is negative, then the current y represents a negative value.
1526 * Flipping it to the positive side.
1527 */
1528 if( A->s < 0 && y != 0 )
1529 y = b - y;
1530
Paul Bakker5121ce52009-01-03 21:22:43 +00001531 *r = y;
1532
1533 return( 0 );
1534}
1535
1536/*
1537 * Fast Montgomery initialization (thanks to Tom St Denis)
1538 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001540{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001541 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001542 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001543
1544 x = m0;
1545 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001546
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001547 for( i = biL; i >= 8; i /= 2 )
1548 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001549
1550 *mm = ~x + 1;
1551}
1552
1553/*
1554 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1555 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001556static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1557 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001558{
Paul Bakker23986e52011-04-24 08:57:21 +00001559 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001560 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001561
1562 memset( T->p, 0, T->n * ciL );
1563
1564 d = T->p;
1565 n = N->n;
1566 m = ( B->n < n ) ? B->n : n;
1567
1568 for( i = 0; i < n; i++ )
1569 {
1570 /*
1571 * T = (T + u0*B + u1*N) / 2^biL
1572 */
1573 u0 = A->p[i];
1574 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1575
1576 mpi_mul_hlp( m, B->p, d, u0 );
1577 mpi_mul_hlp( n, N->p, d, u1 );
1578
1579 *d++ = u0; d[n + 1] = 0;
1580 }
1581
Paul Bakker66d5d072014-06-17 16:39:18 +02001582 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001583
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001584 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001585 mpi_sub_hlp( n, N->p, A->p );
1586 else
1587 /* prevent timing attacks */
1588 mpi_sub_hlp( n, A->p, T->p );
1589}
1590
1591/*
1592 * Montgomery reduction: A = A * R^-1 mod N
1593 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001594static 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 +00001595{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001596 mbedtls_mpi_uint z = 1;
1597 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001598
Paul Bakker8ddb6452013-02-27 14:56:33 +01001599 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001600 U.p = &z;
1601
1602 mpi_montmul( A, &U, N, mm, T );
1603}
1604
1605/*
1606 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1607 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001608int 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 +00001609{
Paul Bakker23986e52011-04-24 08:57:21 +00001610 int ret;
1611 size_t wbits, wsize, one = 1;
1612 size_t i, j, nblimbs;
1613 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001614 mbedtls_mpi_uint ei, mm, state;
1615 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001616 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001617
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001618 if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
1619 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001620
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001621 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1622 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001623
1624 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001625 * Init temps and window size
1626 */
1627 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001628 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1629 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001630 memset( W, 0, sizeof( W ) );
1631
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001632 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001633
1634 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1635 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1636
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001637 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1638 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001639
Paul Bakker5121ce52009-01-03 21:22:43 +00001640 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001641 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1642 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1643 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001644
1645 /*
Paul Bakker50546922012-05-19 08:40:49 +00001646 * Compensate for negative A (and correct at the end)
1647 */
1648 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001649 if( neg )
1650 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001652 Apos.s = 1;
1653 A = &Apos;
1654 }
1655
1656 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001657 * If 1st call, pre-compute R^2 mod N
1658 */
1659 if( _RR == NULL || _RR->p == NULL )
1660 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1662 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1663 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001664
1665 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001666 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001667 }
1668 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001669 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001670
1671 /*
1672 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1673 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001674 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1675 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001676 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001677 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001678
1679 mpi_montmul( &W[1], &RR, N, mm, &T );
1680
1681 /*
1682 * X = R^2 * R^-1 mod N = R mod N
1683 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001684 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001685 mpi_montred( X, N, mm, &T );
1686
1687 if( wsize > 1 )
1688 {
1689 /*
1690 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1691 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001692 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001693
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001694 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1695 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001696
1697 for( i = 0; i < wsize - 1; i++ )
1698 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001699
Paul Bakker5121ce52009-01-03 21:22:43 +00001700 /*
1701 * W[i] = W[i - 1] * W[1]
1702 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001703 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001704 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001705 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1706 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001707
1708 mpi_montmul( &W[i], &W[1], N, mm, &T );
1709 }
1710 }
1711
1712 nblimbs = E->n;
1713 bufsize = 0;
1714 nbits = 0;
1715 wbits = 0;
1716 state = 0;
1717
1718 while( 1 )
1719 {
1720 if( bufsize == 0 )
1721 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001722 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001723 break;
1724
Paul Bakker0d7702c2013-10-29 16:18:35 +01001725 nblimbs--;
1726
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001727 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001728 }
1729
1730 bufsize--;
1731
1732 ei = (E->p[nblimbs] >> bufsize) & 1;
1733
1734 /*
1735 * skip leading 0s
1736 */
1737 if( ei == 0 && state == 0 )
1738 continue;
1739
1740 if( ei == 0 && state == 1 )
1741 {
1742 /*
1743 * out of window, square X
1744 */
1745 mpi_montmul( X, X, N, mm, &T );
1746 continue;
1747 }
1748
1749 /*
1750 * add ei to current window
1751 */
1752 state = 2;
1753
1754 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001755 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001756
1757 if( nbits == wsize )
1758 {
1759 /*
1760 * X = X^wsize R^-1 mod N
1761 */
1762 for( i = 0; i < wsize; i++ )
1763 mpi_montmul( X, X, N, mm, &T );
1764
1765 /*
1766 * X = X * W[wbits] R^-1 mod N
1767 */
1768 mpi_montmul( X, &W[wbits], N, mm, &T );
1769
1770 state--;
1771 nbits = 0;
1772 wbits = 0;
1773 }
1774 }
1775
1776 /*
1777 * process the remaining bits
1778 */
1779 for( i = 0; i < nbits; i++ )
1780 {
1781 mpi_montmul( X, X, N, mm, &T );
1782
1783 wbits <<= 1;
1784
Paul Bakker66d5d072014-06-17 16:39:18 +02001785 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001786 mpi_montmul( X, &W[1], N, mm, &T );
1787 }
1788
1789 /*
1790 * X = A^E * R * R^-1 mod N = A^E mod N
1791 */
1792 mpi_montred( X, N, mm, &T );
1793
Paul Bakkerf6198c12012-05-16 08:02:29 +00001794 if( neg )
1795 {
1796 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001797 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001798 }
1799
Paul Bakker5121ce52009-01-03 21:22:43 +00001800cleanup:
1801
Paul Bakker66d5d072014-06-17 16:39:18 +02001802 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001803 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001804
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001805 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001806
Paul Bakker75a28602014-03-31 12:08:17 +02001807 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001808 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001809
1810 return( ret );
1811}
1812
Paul Bakker5121ce52009-01-03 21:22:43 +00001813/*
1814 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1815 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001817{
Paul Bakker23986e52011-04-24 08:57:21 +00001818 int ret;
1819 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001820 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001821
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001822 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001823
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1825 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001826
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001827 lz = mbedtls_mpi_lsb( &TA );
1828 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001829
Paul Bakker66d5d072014-06-17 16:39:18 +02001830 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001831 lz = lzt;
1832
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001833 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1834 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001835
Paul Bakker5121ce52009-01-03 21:22:43 +00001836 TA.s = TB.s = 1;
1837
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001838 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001839 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001840 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1841 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001842
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001843 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001844 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001845 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1846 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001847 }
1848 else
1849 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001850 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1851 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001852 }
1853 }
1854
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001855 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1856 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001857
1858cleanup:
1859
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001860 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001861
1862 return( ret );
1863}
1864
Paul Bakker33dc46b2014-04-30 16:11:39 +02001865/*
1866 * Fill X with size bytes of random.
1867 *
1868 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001869 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001870 * deterministic, eg for tests).
1871 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001872int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001873 int (*f_rng)(void *, unsigned char *, size_t),
1874 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001875{
Paul Bakker23986e52011-04-24 08:57:21 +00001876 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001877 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001878
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 if( size > MBEDTLS_MPI_MAX_SIZE )
1880 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001881
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1883 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001884
1885cleanup:
1886 return( ret );
1887}
1888
Paul Bakker5121ce52009-01-03 21:22:43 +00001889/*
1890 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1891 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001892int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001893{
1894 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001895 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001896
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001897 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 )
1898 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001899
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001900 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1901 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1902 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001903
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001904 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001905
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001906 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001907 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001908 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001909 goto cleanup;
1910 }
1911
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001912 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1913 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1914 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1915 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001916
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001917 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1918 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1919 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1920 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001921
1922 do
1923 {
1924 while( ( TU.p[0] & 1 ) == 0 )
1925 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001926 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001927
1928 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1929 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001930 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1931 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001932 }
1933
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001934 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1935 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001936 }
1937
1938 while( ( TV.p[0] & 1 ) == 0 )
1939 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001940 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001941
1942 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1943 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001944 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1945 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001946 }
1947
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001948 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1949 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001950 }
1951
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001952 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001953 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001954 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1955 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1956 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001957 }
1958 else
1959 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001960 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1961 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1962 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001963 }
1964 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001965 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001966
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001967 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1968 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001970 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1971 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001972
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001973 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001974
1975cleanup:
1976
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001977 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1978 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1979 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001980
1981 return( ret );
1982}
1983
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001984#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001985
Paul Bakker5121ce52009-01-03 21:22:43 +00001986static const int small_prime[] =
1987{
1988 3, 5, 7, 11, 13, 17, 19, 23,
1989 29, 31, 37, 41, 43, 47, 53, 59,
1990 61, 67, 71, 73, 79, 83, 89, 97,
1991 101, 103, 107, 109, 113, 127, 131, 137,
1992 139, 149, 151, 157, 163, 167, 173, 179,
1993 181, 191, 193, 197, 199, 211, 223, 227,
1994 229, 233, 239, 241, 251, 257, 263, 269,
1995 271, 277, 281, 283, 293, 307, 311, 313,
1996 317, 331, 337, 347, 349, 353, 359, 367,
1997 373, 379, 383, 389, 397, 401, 409, 419,
1998 421, 431, 433, 439, 443, 449, 457, 461,
1999 463, 467, 479, 487, 491, 499, 503, 509,
2000 521, 523, 541, 547, 557, 563, 569, 571,
2001 577, 587, 593, 599, 601, 607, 613, 617,
2002 619, 631, 641, 643, 647, 653, 659, 661,
2003 673, 677, 683, 691, 701, 709, 719, 727,
2004 733, 739, 743, 751, 757, 761, 769, 773,
2005 787, 797, 809, 811, 821, 823, 827, 829,
2006 839, 853, 857, 859, 863, 877, 881, 883,
2007 887, 907, 911, 919, 929, 937, 941, 947,
2008 953, 967, 971, 977, 983, 991, 997, -103
2009};
2010
2011/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002012 * Small divisors test (X must be positive)
2013 *
2014 * Return values:
2015 * 0: no small factor (possible prime, more tests needed)
2016 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002017 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002018 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002019 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002020static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002021{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002022 int ret = 0;
2023 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002024 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002025
Paul Bakker5121ce52009-01-03 21:22:43 +00002026 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002027 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002028
2029 for( i = 0; small_prime[i] > 0; i++ )
2030 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002031 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002032 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002035
2036 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002037 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002038 }
2039
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002040cleanup:
2041 return( ret );
2042}
2043
2044/*
2045 * Miller-Rabin pseudo-primality test (HAC 4.24)
2046 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002047static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002048 int (*f_rng)(void *, unsigned char *, size_t),
2049 void *p_rng )
2050{
Pascal Junodb99183d2015-03-11 16:49:45 +01002051 int ret, count;
2052 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002053 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002054
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002055 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2056 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002057
Paul Bakker5121ce52009-01-03 21:22:43 +00002058 /*
2059 * W = |X| - 1
2060 * R = W >> lsb( W )
2061 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002062 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2063 s = mbedtls_mpi_lsb( &W );
2064 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2065 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002066
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002067 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002068 /*
2069 * HAC, table 4.4
2070 */
2071 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2072 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2073 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2074
2075 for( i = 0; i < n; i++ )
2076 {
2077 /*
2078 * pick a random A, 1 < A < |X| - 1
2079 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002080 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002081
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002082 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00002083 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002084 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002085 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00002086 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002087 A.p[0] |= 3;
2088
Pascal Junodb99183d2015-03-11 16:49:45 +01002089 count = 0;
2090 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002091 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002092
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002093 j = mbedtls_mpi_bitlen( &A );
2094 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002095 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002096 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002097 }
2098
2099 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002100 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002101 }
2102
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002103 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2104 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002105
2106 /*
2107 * A = A^R mod |X|
2108 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002109 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002111 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2112 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002113 continue;
2114
2115 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002116 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002117 {
2118 /*
2119 * A = A * A mod |X|
2120 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002121 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2122 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002123
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002124 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002125 break;
2126
2127 j++;
2128 }
2129
2130 /*
2131 * not prime if A != |X| - 1 or A == 1
2132 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002133 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2134 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002135 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002136 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002137 break;
2138 }
2139 }
2140
2141cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002142 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2143 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002144
2145 return( ret );
2146}
2147
2148/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002149 * Pseudo-primality test: small factors, then Miller-Rabin
2150 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002151int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002152 int (*f_rng)(void *, unsigned char *, size_t),
2153 void *p_rng )
2154{
2155 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002156 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002157
2158 XX.s = 1;
2159 XX.n = X->n;
2160 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002161
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002162 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2163 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2164 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002165
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002166 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002167 return( 0 );
2168
2169 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2170 {
2171 if( ret == 1 )
2172 return( 0 );
2173
2174 return( ret );
2175 }
2176
2177 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2178}
2179
2180/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002181 * Prime number generation
2182 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002183int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002184 int (*f_rng)(void *, unsigned char *, size_t),
2185 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002186{
Paul Bakker23986e52011-04-24 08:57:21 +00002187 int ret;
2188 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002189 mbedtls_mpi_uint r;
2190 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002192 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2193 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002194
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002195 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002196
2197 n = BITS_TO_LIMBS( nbits );
2198
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002199 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002200
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002201 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002202 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002203
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002204 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002205
2206 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002207
2208 if( dh_flag == 0 )
2209 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002210 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002211 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002212 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002213 goto cleanup;
2214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002215 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002216 }
2217 }
2218 else
2219 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002220 /*
2221 * An necessary condition for Y and X = 2Y + 1 to be prime
2222 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2223 * Make sure it is satisfied, while keeping X = 3 mod 4
2224 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002225
2226 X->p[0] |= 2;
2227
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002228 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002229 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002230 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002231 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002232 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002233
2234 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002235 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2236 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002237
2238 while( 1 )
2239 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002240 /*
2241 * First, check small factors for X and Y
2242 * before doing Miller-Rabin on any of them
2243 */
2244 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2245 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2246 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2247 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002248 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002249 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002250 }
2251
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002252 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002253 goto cleanup;
2254
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002255 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002256 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002257 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2258 * so up Y by 6 and X by 12.
2259 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002260 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2261 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002262 }
2263 }
2264
2265cleanup:
2266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002267 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002268
2269 return( ret );
2270}
2271
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002273
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002274#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002275
Paul Bakker23986e52011-04-24 08:57:21 +00002276#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002277
2278static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2279{
2280 { 693, 609, 21 },
2281 { 1764, 868, 28 },
2282 { 768454923, 542167814, 1 }
2283};
2284
Paul Bakker5121ce52009-01-03 21:22:43 +00002285/*
2286 * Checkup routine
2287 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002289{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002290 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002291 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002293 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2294 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002295
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002296 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002297 "EFE021C2645FD1DC586E69184AF4A31E" \
2298 "D5F53E93B5F123FA41680867BA110131" \
2299 "944FE7952E2517337780CB0DB80E61AA" \
2300 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2301
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002302 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002303 "B2E7EFD37075B9F03FF989C7C5051C20" \
2304 "34D2A323810251127E7BF8625A4F49A5" \
2305 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2306 "5B5C25763222FEFCCFC38B832366C29E" ) );
2307
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002308 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002309 "0066A198186C18C10B2F5ED9B522752A" \
2310 "9830B69916E535C8F047518A889A43A5" \
2311 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2312
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002313 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002314
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002315 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002316 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2317 "9E857EA95A03512E2BAE7391688D264A" \
2318 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2319 "8001B72E848A38CAE1C65F78E56ABDEF" \
2320 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2321 "ECF677152EF804370C1A305CAF3B5BF1" \
2322 "30879B56C61DE584A0F53A2447A51E" ) );
2323
2324 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002325 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002327 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002328 {
2329 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002331
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002332 ret = 1;
2333 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002334 }
2335
2336 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002337 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002338
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002339 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002342 "256567336059E52CAE22925474705F39A94" ) );
2343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002344 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002345 "6613F26162223DF488E9CD48CC132C7A" \
2346 "0AC93C701B001B092E4E5B9F73BCD27B" \
2347 "9EE50D0657C77F374E903CDFA4C642" ) );
2348
2349 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002350 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002351
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002352 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2353 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002354 {
2355 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002356 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002357
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002358 ret = 1;
2359 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002360 }
2361
2362 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002363 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002364
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002365 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002366
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002368 "36E139AEA55215609D2816998ED020BB" \
2369 "BD96C37890F65171D948E9BC7CBAA4D9" \
2370 "325D24D6A3C12710F10A09FA08AB87" ) );
2371
2372 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002373 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002375 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002376 {
2377 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002378 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002379
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002380 ret = 1;
2381 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002382 }
2383
2384 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002386
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002387 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002389 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002390 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2391 "C3DBA76456363A10869622EAC2DD84EC" \
2392 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2393
2394 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002395 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002397 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002398 {
2399 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002400 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002401
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002402 ret = 1;
2403 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002404 }
2405
2406 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002407 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002408
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002409 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002410 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002411
Paul Bakker66d5d072014-06-17 16:39:18 +02002412 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002413 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002414 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2415 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002416
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002417 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002418
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002419 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002420 {
2421 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002422 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002423
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002424 ret = 1;
2425 goto cleanup;
2426 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002427 }
2428
2429 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002430 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002431
Paul Bakker5121ce52009-01-03 21:22:43 +00002432cleanup:
2433
2434 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002435 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002436
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002437 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2438 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002439
2440 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002441 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002442
2443 return( ret );
2444}
2445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002446#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002447
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002448#endif /* MBEDTLS_BIGNUM_C */