blob: 383d3f652bf4ad71ac19bf8865457df98457612d [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;
Paul Bakker5121ce52009-01-03 21:22:43 +0000887
888 if( X == B )
889 {
Janos Follath5429c0a2015-10-25 12:29:13 +0100890 if( B == A )
891 {
892 // Making a temporary copy instead of shifting by one to deny
893 // the possibility of corresponding side-channel attacks.
894 mbedtls_mpi TB;
Janos Follathd0e0c032015-10-25 10:58:03 +0100895
Janos Follath5429c0a2015-10-25 12:29:13 +0100896 mbedtls_mpi_init( &TB );
897 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
898
899 return mbedtls_mpi_add_abs( X, A, &TB );
900 }
Janos Follathd0e0c032015-10-25 10:58:03 +0100901
Janos Follath5429c0a2015-10-25 12:29:13 +0100902 B = A; A = X;
Paul Bakker5121ce52009-01-03 21:22:43 +0000903 }
904
905 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200906 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200907
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000908 /*
909 * X should always be positive as a result of unsigned additions.
910 */
911 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000912
Paul Bakker23986e52011-04-24 08:57:21 +0000913 for( j = B->n; j > 0; j-- )
914 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000915 break;
916
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200917 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000918
919 o = B->p; p = X->p; c = 0;
920
Paul Bakker23986e52011-04-24 08:57:21 +0000921 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000922 {
923 *p += c; c = ( *p < c );
924 *p += *o; c += ( *p < *o );
925 }
926
927 while( c != 0 )
928 {
929 if( i >= X->n )
930 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200931 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000932 p = X->p + i;
933 }
934
Paul Bakker2d319fd2012-09-16 21:34:26 +0000935 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000936 }
937
938cleanup:
939
940 return( ret );
941}
942
943/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200944 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000945 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200946static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000947{
Paul Bakker23986e52011-04-24 08:57:21 +0000948 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200949 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000950
951 for( i = c = 0; i < n; i++, s++, d++ )
952 {
953 z = ( *d < c ); *d -= c;
954 c = ( *d < *s ) + z; *d -= *s;
955 }
956
957 while( c != 0 )
958 {
959 z = ( *d < c ); *d -= c;
960 c = z; i++; d++;
961 }
962}
963
964/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100965 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000966 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200967int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000968{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200969 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000970 int ret;
971 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000972
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200973 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
974 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000975
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200976 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000977
978 if( X == B )
979 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200980 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000981 B = &TB;
982 }
983
984 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200985 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000986
Paul Bakker1ef7a532009-06-20 10:50:55 +0000987 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100988 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000989 */
990 X->s = 1;
991
Paul Bakker5121ce52009-01-03 21:22:43 +0000992 ret = 0;
993
Paul Bakker23986e52011-04-24 08:57:21 +0000994 for( n = B->n; n > 0; n-- )
995 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000996 break;
997
Paul Bakker23986e52011-04-24 08:57:21 +0000998 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000999
1000cleanup:
1001
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001002 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001003
1004 return( ret );
1005}
1006
1007/*
1008 * Signed addition: X = A + B
1009 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001010int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001011{
1012 int ret, s = A->s;
1013
1014 if( A->s * B->s < 0 )
1015 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001017 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001018 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001019 X->s = s;
1020 }
1021 else
1022 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001023 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001024 X->s = -s;
1025 }
1026 }
1027 else
1028 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001029 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001030 X->s = s;
1031 }
1032
1033cleanup:
1034
1035 return( ret );
1036}
1037
1038/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001039 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001040 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001041int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001042{
1043 int ret, s = A->s;
1044
1045 if( A->s * B->s > 0 )
1046 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001047 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001048 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001049 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001050 X->s = s;
1051 }
1052 else
1053 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001054 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001055 X->s = -s;
1056 }
1057 }
1058 else
1059 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001060 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001061 X->s = s;
1062 }
1063
1064cleanup:
1065
1066 return( ret );
1067}
1068
1069/*
1070 * Signed addition: X = A + b
1071 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001072int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001073{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001074 mbedtls_mpi _B;
1075 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001076
1077 p[0] = ( b < 0 ) ? -b : b;
1078 _B.s = ( b < 0 ) ? -1 : 1;
1079 _B.n = 1;
1080 _B.p = p;
1081
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001082 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001083}
1084
1085/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001086 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001087 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001088int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001089{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001090 mbedtls_mpi _B;
1091 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001092
1093 p[0] = ( b < 0 ) ? -b : b;
1094 _B.s = ( b < 0 ) ? -1 : 1;
1095 _B.n = 1;
1096 _B.p = p;
1097
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001098 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001099}
1100
1101/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001102 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001103 */
1104static
1105#if defined(__APPLE__) && defined(__arm__)
1106/*
1107 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1108 * appears to need this to prevent bad ARM code generation at -O3.
1109 */
1110__attribute__ ((noinline))
1111#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001112void 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 +00001113{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001114 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001115
1116#if defined(MULADDC_HUIT)
1117 for( ; i >= 8; i -= 8 )
1118 {
1119 MULADDC_INIT
1120 MULADDC_HUIT
1121 MULADDC_STOP
1122 }
1123
1124 for( ; i > 0; i-- )
1125 {
1126 MULADDC_INIT
1127 MULADDC_CORE
1128 MULADDC_STOP
1129 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001130#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001131 for( ; i >= 16; i -= 16 )
1132 {
1133 MULADDC_INIT
1134 MULADDC_CORE MULADDC_CORE
1135 MULADDC_CORE MULADDC_CORE
1136 MULADDC_CORE MULADDC_CORE
1137 MULADDC_CORE MULADDC_CORE
1138
1139 MULADDC_CORE MULADDC_CORE
1140 MULADDC_CORE MULADDC_CORE
1141 MULADDC_CORE MULADDC_CORE
1142 MULADDC_CORE MULADDC_CORE
1143 MULADDC_STOP
1144 }
1145
1146 for( ; i >= 8; i -= 8 )
1147 {
1148 MULADDC_INIT
1149 MULADDC_CORE MULADDC_CORE
1150 MULADDC_CORE MULADDC_CORE
1151
1152 MULADDC_CORE MULADDC_CORE
1153 MULADDC_CORE MULADDC_CORE
1154 MULADDC_STOP
1155 }
1156
1157 for( ; i > 0; i-- )
1158 {
1159 MULADDC_INIT
1160 MULADDC_CORE
1161 MULADDC_STOP
1162 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001163#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001164
1165 t++;
1166
1167 do {
1168 *d += c; c = ( *d < c ); d++;
1169 }
1170 while( c != 0 );
1171}
1172
1173/*
1174 * Baseline multiplication: X = A * B (HAC 14.12)
1175 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001176int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001177{
Paul Bakker23986e52011-04-24 08:57:21 +00001178 int ret;
1179 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001180 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001182 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001184 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1185 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001186
Paul Bakker23986e52011-04-24 08:57:21 +00001187 for( i = A->n; i > 0; i-- )
1188 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001189 break;
1190
Paul Bakker23986e52011-04-24 08:57:21 +00001191 for( j = B->n; j > 0; j-- )
1192 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001193 break;
1194
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001195 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1196 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001197
Paul Bakker23986e52011-04-24 08:57:21 +00001198 for( i++; j > 0; j-- )
1199 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001200
1201 X->s = A->s * B->s;
1202
1203cleanup:
1204
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001205 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001206
1207 return( ret );
1208}
1209
1210/*
1211 * Baseline multiplication: X = A * b
1212 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001213int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001214{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001215 mbedtls_mpi _B;
1216 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001217
1218 _B.s = 1;
1219 _B.n = 1;
1220 _B.p = p;
1221 p[0] = b;
1222
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001223 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001224}
1225
1226/*
Simon Butcher7ebe2782015-12-28 00:05:30 +00001227 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1228 * mbedtls_mpi_uint divisor, d
Simon Butcherea303e32015-11-26 23:43:34 +00001229 */
Simon Butcher7ebe2782015-12-28 00:05:30 +00001230static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1231 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcherea303e32015-11-26 23:43:34 +00001232{
Manuel Pégourié-Gonnard5a8396e2015-12-01 10:27:00 +01001233#if defined(MBEDTLS_HAVE_UDBL)
1234 mbedtls_t_udbl dividend, quotient;
Simon Butcher7ebe2782015-12-28 00:05:30 +00001235#else
Simon Butcher61891752016-01-03 00:24:34 +00001236 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1237 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcher7ebe2782015-12-28 00:05:30 +00001238 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1239 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher61891752016-01-03 00:24:34 +00001240 size_t s;
Manuel Pégourié-Gonnard5a8396e2015-12-01 10:27:00 +01001241#endif
1242
Simon Butcherea303e32015-11-26 23:43:34 +00001243 /*
1244 * Check for overflow
1245 */
Simon Butcher7ebe2782015-12-28 00:05:30 +00001246 if( 0 == d || u1 >= d )
Simon Butcherea303e32015-11-26 23:43:34 +00001247 {
Simon Butcher7ebe2782015-12-28 00:05:30 +00001248 if (r != NULL) *r = ~0;
Simon Butcherea303e32015-11-26 23:43:34 +00001249
Simon Butcher7ebe2782015-12-28 00:05:30 +00001250 return ( ~0 );
Simon Butcherea303e32015-11-26 23:43:34 +00001251 }
1252
1253#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcherea303e32015-11-26 23:43:34 +00001254 dividend = (mbedtls_t_udbl) u1 << biL;
1255 dividend |= (mbedtls_t_udbl) u0;
1256 quotient = dividend / d;
1257 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1258 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1259
1260 if( r != NULL )
Simon Butcher61891752016-01-03 00:24:34 +00001261 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcherea303e32015-11-26 23:43:34 +00001262
1263 return (mbedtls_mpi_uint) quotient;
1264#else
Simon Butcherea303e32015-11-26 23:43:34 +00001265
1266 /*
1267 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1268 * Vol. 2 - Seminumerical Algorithms, Knuth
1269 */
1270
1271 /*
1272 * Normalize the divisor, d, and dividend, u0, u1
1273 */
1274 s = mbedtls_clz( d );
1275 d = d << s;
1276
1277 u1 = u1 << s;
Simon Butcher61891752016-01-03 00:24:34 +00001278 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcherea303e32015-11-26 23:43:34 +00001279 u0 = u0 << s;
1280
1281 d1 = d >> biH;
Simon Butcher61891752016-01-03 00:24:34 +00001282 d0 = d & uint_halfword_mask;
Simon Butcherea303e32015-11-26 23:43:34 +00001283
1284 u0_msw = u0 >> biH;
Simon Butcher61891752016-01-03 00:24:34 +00001285 u0_lsw = u0 & uint_halfword_mask;
Simon Butcherea303e32015-11-26 23:43:34 +00001286
1287 /*
1288 * Find the first quotient and remainder
1289 */
1290 q1 = u1 / d1;
1291 r0 = u1 - d1 * q1;
1292
1293 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1294 {
1295 q1 -= 1;
1296 r0 += d1;
1297
1298 if ( r0 >= radix ) break;
1299 }
1300
Simon Butcher7ebe2782015-12-28 00:05:30 +00001301 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcherea303e32015-11-26 23:43:34 +00001302 q0 = rAX / d1;
1303 r0 = rAX - q0 * d1;
1304
1305 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1306 {
1307 q0 -= 1;
1308 r0 += d1;
1309
1310 if ( r0 >= radix ) break;
1311 }
1312
1313 if (r != NULL)
Simon Butcher7ebe2782015-12-28 00:05:30 +00001314 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcherea303e32015-11-26 23:43:34 +00001315
1316 quotient = q1 * radix + q0;
1317
1318 return quotient;
1319#endif
1320}
1321
1322/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001323 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001324 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001325int 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 +00001326{
Paul Bakker23986e52011-04-24 08:57:21 +00001327 int ret;
1328 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001329 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001330
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001331 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1332 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001334 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1335 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001336
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001337 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001338 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001339 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1340 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001341 return( 0 );
1342 }
1343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001344 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1345 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001346 X.s = Y.s = 1;
1347
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001348 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1349 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1350 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1351 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001352
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001353 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001354 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001355 {
1356 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001357 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1358 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001359 }
1360 else k = 0;
1361
1362 n = X.n - 1;
1363 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001364 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001367 {
1368 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001369 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001370 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001371 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001372
1373 for( i = n; i > t ; i-- )
1374 {
1375 if( X.p[i] >= Y.p[t] )
1376 Z.p[i - t - 1] = ~0;
1377 else
1378 {
Simon Butcherea303e32015-11-26 23:43:34 +00001379 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1380 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001381 }
1382
1383 Z.p[i - t - 1]++;
1384 do
1385 {
1386 Z.p[i - t - 1]--;
1387
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001388 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001389 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001390 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001393 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001394 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1395 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001396 T2.p[2] = X.p[i];
1397 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001398 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1401 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1402 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001403
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001404 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001405 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1407 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1408 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001409 Z.p[i - t - 1]--;
1410 }
1411 }
1412
1413 if( Q != NULL )
1414 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001415 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001416 Q->s = A->s * B->s;
1417 }
1418
1419 if( R != NULL )
1420 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001421 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001422 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001423 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001424
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001425 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001426 R->s = 1;
1427 }
1428
1429cleanup:
1430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001431 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1432 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001433
1434 return( ret );
1435}
1436
1437/*
1438 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001439 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001440int 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 +00001441{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001442 mbedtls_mpi _B;
1443 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001444
1445 p[0] = ( b < 0 ) ? -b : b;
1446 _B.s = ( b < 0 ) ? -1 : 1;
1447 _B.n = 1;
1448 _B.p = p;
1449
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001450 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001451}
1452
1453/*
1454 * Modulo: R = A mod B
1455 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001456int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001457{
1458 int ret;
1459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001460 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1461 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001463 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001465 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1466 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001468 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1469 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001470
1471cleanup:
1472
1473 return( ret );
1474}
1475
1476/*
1477 * Modulo: r = A mod b
1478 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001479int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001480{
Paul Bakker23986e52011-04-24 08:57:21 +00001481 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001482 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001483
1484 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001485 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
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_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001489
1490 /*
1491 * handle trivial cases
1492 */
1493 if( b == 1 )
1494 {
1495 *r = 0;
1496 return( 0 );
1497 }
1498
1499 if( b == 2 )
1500 {
1501 *r = A->p[0] & 1;
1502 return( 0 );
1503 }
1504
1505 /*
1506 * general case
1507 */
Paul Bakker23986e52011-04-24 08:57:21 +00001508 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001509 {
Paul Bakker23986e52011-04-24 08:57:21 +00001510 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001511 y = ( y << biH ) | ( x >> biH );
1512 z = y / b;
1513 y -= z * b;
1514
1515 x <<= biH;
1516 y = ( y << biH ) | ( x >> biH );
1517 z = y / b;
1518 y -= z * b;
1519 }
1520
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001521 /*
1522 * If A is negative, then the current y represents a negative value.
1523 * Flipping it to the positive side.
1524 */
1525 if( A->s < 0 && y != 0 )
1526 y = b - y;
1527
Paul Bakker5121ce52009-01-03 21:22:43 +00001528 *r = y;
1529
1530 return( 0 );
1531}
1532
1533/*
1534 * Fast Montgomery initialization (thanks to Tom St Denis)
1535 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001536static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001537{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001538 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001539 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001540
1541 x = m0;
1542 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001543
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001544 for( i = biL; i >= 8; i /= 2 )
1545 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001546
1547 *mm = ~x + 1;
1548}
1549
1550/*
1551 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1552 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001553static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1554 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001555{
Paul Bakker23986e52011-04-24 08:57:21 +00001556 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001557 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001558
1559 memset( T->p, 0, T->n * ciL );
1560
1561 d = T->p;
1562 n = N->n;
1563 m = ( B->n < n ) ? B->n : n;
1564
1565 for( i = 0; i < n; i++ )
1566 {
1567 /*
1568 * T = (T + u0*B + u1*N) / 2^biL
1569 */
1570 u0 = A->p[i];
1571 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1572
1573 mpi_mul_hlp( m, B->p, d, u0 );
1574 mpi_mul_hlp( n, N->p, d, u1 );
1575
1576 *d++ = u0; d[n + 1] = 0;
1577 }
1578
Paul Bakker66d5d072014-06-17 16:39:18 +02001579 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001580
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001581 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001582 mpi_sub_hlp( n, N->p, A->p );
1583 else
1584 /* prevent timing attacks */
1585 mpi_sub_hlp( n, A->p, T->p );
1586}
1587
1588/*
1589 * Montgomery reduction: A = A * R^-1 mod N
1590 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001591static 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 +00001592{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001593 mbedtls_mpi_uint z = 1;
1594 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001595
Paul Bakker8ddb6452013-02-27 14:56:33 +01001596 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001597 U.p = &z;
1598
1599 mpi_montmul( A, &U, N, mm, T );
1600}
1601
1602/*
1603 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1604 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001605int 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 +00001606{
Paul Bakker23986e52011-04-24 08:57:21 +00001607 int ret;
1608 size_t wbits, wsize, one = 1;
1609 size_t i, j, nblimbs;
1610 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001611 mbedtls_mpi_uint ei, mm, state;
1612 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001613 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001615 if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
1616 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001617
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001618 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1619 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001620
1621 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001622 * Init temps and window size
1623 */
1624 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001625 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1626 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001627 memset( W, 0, sizeof( W ) );
1628
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001629 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001630
1631 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1632 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1633
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001634 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1635 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001636
Paul Bakker5121ce52009-01-03 21:22:43 +00001637 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001638 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1639 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1640 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001641
1642 /*
Paul Bakker50546922012-05-19 08:40:49 +00001643 * Compensate for negative A (and correct at the end)
1644 */
1645 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001646 if( neg )
1647 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001648 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001649 Apos.s = 1;
1650 A = &Apos;
1651 }
1652
1653 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001654 * If 1st call, pre-compute R^2 mod N
1655 */
1656 if( _RR == NULL || _RR->p == NULL )
1657 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001658 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1659 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1660 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001661
1662 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001663 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001664 }
1665 else
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 /*
1669 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1670 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1672 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001673 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001674 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001675
1676 mpi_montmul( &W[1], &RR, N, mm, &T );
1677
1678 /*
1679 * X = R^2 * R^-1 mod N = R mod N
1680 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001681 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001682 mpi_montred( X, N, mm, &T );
1683
1684 if( wsize > 1 )
1685 {
1686 /*
1687 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1688 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001689 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001690
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001691 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1692 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001693
1694 for( i = 0; i < wsize - 1; i++ )
1695 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001696
Paul Bakker5121ce52009-01-03 21:22:43 +00001697 /*
1698 * W[i] = W[i - 1] * W[1]
1699 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001700 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001701 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001702 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1703 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001704
1705 mpi_montmul( &W[i], &W[1], N, mm, &T );
1706 }
1707 }
1708
1709 nblimbs = E->n;
1710 bufsize = 0;
1711 nbits = 0;
1712 wbits = 0;
1713 state = 0;
1714
1715 while( 1 )
1716 {
1717 if( bufsize == 0 )
1718 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001719 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001720 break;
1721
Paul Bakker0d7702c2013-10-29 16:18:35 +01001722 nblimbs--;
1723
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001724 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001725 }
1726
1727 bufsize--;
1728
1729 ei = (E->p[nblimbs] >> bufsize) & 1;
1730
1731 /*
1732 * skip leading 0s
1733 */
1734 if( ei == 0 && state == 0 )
1735 continue;
1736
1737 if( ei == 0 && state == 1 )
1738 {
1739 /*
1740 * out of window, square X
1741 */
1742 mpi_montmul( X, X, N, mm, &T );
1743 continue;
1744 }
1745
1746 /*
1747 * add ei to current window
1748 */
1749 state = 2;
1750
1751 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001752 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001753
1754 if( nbits == wsize )
1755 {
1756 /*
1757 * X = X^wsize R^-1 mod N
1758 */
1759 for( i = 0; i < wsize; i++ )
1760 mpi_montmul( X, X, N, mm, &T );
1761
1762 /*
1763 * X = X * W[wbits] R^-1 mod N
1764 */
1765 mpi_montmul( X, &W[wbits], N, mm, &T );
1766
1767 state--;
1768 nbits = 0;
1769 wbits = 0;
1770 }
1771 }
1772
1773 /*
1774 * process the remaining bits
1775 */
1776 for( i = 0; i < nbits; i++ )
1777 {
1778 mpi_montmul( X, X, N, mm, &T );
1779
1780 wbits <<= 1;
1781
Paul Bakker66d5d072014-06-17 16:39:18 +02001782 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001783 mpi_montmul( X, &W[1], N, mm, &T );
1784 }
1785
1786 /*
1787 * X = A^E * R * R^-1 mod N = A^E mod N
1788 */
1789 mpi_montred( X, N, mm, &T );
1790
Paul Bakkerf6198c12012-05-16 08:02:29 +00001791 if( neg )
1792 {
1793 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001794 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001795 }
1796
Paul Bakker5121ce52009-01-03 21:22:43 +00001797cleanup:
1798
Paul Bakker66d5d072014-06-17 16:39:18 +02001799 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001800 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001801
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001802 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001803
Paul Bakker75a28602014-03-31 12:08:17 +02001804 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001805 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001806
1807 return( ret );
1808}
1809
Paul Bakker5121ce52009-01-03 21:22:43 +00001810/*
1811 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1812 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001813int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001814{
Paul Bakker23986e52011-04-24 08:57:21 +00001815 int ret;
1816 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001817 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001818
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001819 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001820
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001821 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1822 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001823
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824 lz = mbedtls_mpi_lsb( &TA );
1825 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001826
Paul Bakker66d5d072014-06-17 16:39:18 +02001827 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001828 lz = lzt;
1829
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1831 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001832
Paul Bakker5121ce52009-01-03 21:22:43 +00001833 TA.s = TB.s = 1;
1834
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001835 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001836 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001837 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1838 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001839
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001840 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001841 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001842 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1843 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001844 }
1845 else
1846 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001847 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1848 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001849 }
1850 }
1851
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001852 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1853 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001854
1855cleanup:
1856
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001857 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001858
1859 return( ret );
1860}
1861
Paul Bakker33dc46b2014-04-30 16:11:39 +02001862/*
1863 * Fill X with size bytes of random.
1864 *
1865 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001866 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001867 * deterministic, eg for tests).
1868 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001869int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001870 int (*f_rng)(void *, unsigned char *, size_t),
1871 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001872{
Paul Bakker23986e52011-04-24 08:57:21 +00001873 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001874 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001875
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001876 if( size > MBEDTLS_MPI_MAX_SIZE )
1877 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001878
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1880 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001881
1882cleanup:
1883 return( ret );
1884}
1885
Paul Bakker5121ce52009-01-03 21:22:43 +00001886/*
1887 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1888 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001889int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001890{
1891 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001892 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001893
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 )
1895 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001896
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001897 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1898 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1899 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001900
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001901 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001902
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001903 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001904 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001905 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001906 goto cleanup;
1907 }
1908
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001909 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1910 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1911 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1912 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001913
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001914 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1915 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1916 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1917 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001918
1919 do
1920 {
1921 while( ( TU.p[0] & 1 ) == 0 )
1922 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001923 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001924
1925 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1926 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001927 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1928 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001929 }
1930
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001931 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1932 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001933 }
1934
1935 while( ( TV.p[0] & 1 ) == 0 )
1936 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001937 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001938
1939 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1940 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001941 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1942 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001943 }
1944
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001945 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1946 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001947 }
1948
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001949 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001950 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001951 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1952 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1953 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001954 }
1955 else
1956 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001957 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1958 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1959 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001960 }
1961 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001962 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001963
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001964 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1965 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001966
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001967 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1968 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001970 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001971
1972cleanup:
1973
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001974 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1975 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1976 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001977
1978 return( ret );
1979}
1980
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001981#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001982
Paul Bakker5121ce52009-01-03 21:22:43 +00001983static const int small_prime[] =
1984{
1985 3, 5, 7, 11, 13, 17, 19, 23,
1986 29, 31, 37, 41, 43, 47, 53, 59,
1987 61, 67, 71, 73, 79, 83, 89, 97,
1988 101, 103, 107, 109, 113, 127, 131, 137,
1989 139, 149, 151, 157, 163, 167, 173, 179,
1990 181, 191, 193, 197, 199, 211, 223, 227,
1991 229, 233, 239, 241, 251, 257, 263, 269,
1992 271, 277, 281, 283, 293, 307, 311, 313,
1993 317, 331, 337, 347, 349, 353, 359, 367,
1994 373, 379, 383, 389, 397, 401, 409, 419,
1995 421, 431, 433, 439, 443, 449, 457, 461,
1996 463, 467, 479, 487, 491, 499, 503, 509,
1997 521, 523, 541, 547, 557, 563, 569, 571,
1998 577, 587, 593, 599, 601, 607, 613, 617,
1999 619, 631, 641, 643, 647, 653, 659, 661,
2000 673, 677, 683, 691, 701, 709, 719, 727,
2001 733, 739, 743, 751, 757, 761, 769, 773,
2002 787, 797, 809, 811, 821, 823, 827, 829,
2003 839, 853, 857, 859, 863, 877, 881, 883,
2004 887, 907, 911, 919, 929, 937, 941, 947,
2005 953, 967, 971, 977, 983, 991, 997, -103
2006};
2007
2008/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002009 * Small divisors test (X must be positive)
2010 *
2011 * Return values:
2012 * 0: no small factor (possible prime, more tests needed)
2013 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002014 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002015 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002016 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002017static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002018{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002019 int ret = 0;
2020 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002021 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
Paul Bakker5121ce52009-01-03 21:22:43 +00002023 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002024 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002025
2026 for( i = 0; small_prime[i] > 0; i++ )
2027 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002028 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002029 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002030
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002031 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002032
2033 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002035 }
2036
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002037cleanup:
2038 return( ret );
2039}
2040
2041/*
2042 * Miller-Rabin pseudo-primality test (HAC 4.24)
2043 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002044static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002045 int (*f_rng)(void *, unsigned char *, size_t),
2046 void *p_rng )
2047{
Pascal Junodb99183d2015-03-11 16:49:45 +01002048 int ret, count;
2049 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002050 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002051
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2053 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002054
Paul Bakker5121ce52009-01-03 21:22:43 +00002055 /*
2056 * W = |X| - 1
2057 * R = W >> lsb( W )
2058 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002059 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2060 s = mbedtls_mpi_lsb( &W );
2061 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2062 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002063
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002064 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002065 /*
2066 * HAC, table 4.4
2067 */
2068 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2069 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2070 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2071
2072 for( i = 0; i < n; i++ )
2073 {
2074 /*
2075 * pick a random A, 1 < A < |X| - 1
2076 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002077 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002078
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002079 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00002080 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002081 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002082 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00002083 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002084 A.p[0] |= 3;
2085
Pascal Junodb99183d2015-03-11 16:49:45 +01002086 count = 0;
2087 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002088 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002089
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002090 j = mbedtls_mpi_bitlen( &A );
2091 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002092 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002093 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002094 }
2095
2096 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002097 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002098 }
2099
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002100 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2101 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002102
2103 /*
2104 * A = A^R mod |X|
2105 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002106 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002107
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002108 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2109 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002110 continue;
2111
2112 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002113 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002114 {
2115 /*
2116 * A = A * A mod |X|
2117 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002118 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2119 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002120
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002121 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002122 break;
2123
2124 j++;
2125 }
2126
2127 /*
2128 * not prime if A != |X| - 1 or A == 1
2129 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002130 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2131 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002132 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002133 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002134 break;
2135 }
2136 }
2137
2138cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002139 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2140 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002141
2142 return( ret );
2143}
2144
2145/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002146 * Pseudo-primality test: small factors, then Miller-Rabin
2147 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002148int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002149 int (*f_rng)(void *, unsigned char *, size_t),
2150 void *p_rng )
2151{
2152 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002153 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002154
2155 XX.s = 1;
2156 XX.n = X->n;
2157 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002158
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002159 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2160 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2161 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002162
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002163 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002164 return( 0 );
2165
2166 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2167 {
2168 if( ret == 1 )
2169 return( 0 );
2170
2171 return( ret );
2172 }
2173
2174 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2175}
2176
2177/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002178 * Prime number generation
2179 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002180int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002181 int (*f_rng)(void *, unsigned char *, size_t),
2182 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002183{
Paul Bakker23986e52011-04-24 08:57:21 +00002184 int ret;
2185 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002186 mbedtls_mpi_uint r;
2187 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002189 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2190 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002192 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002193
2194 n = BITS_TO_LIMBS( nbits );
2195
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002196 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002197
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002198 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002199 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002200
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002201 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002202
2203 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002204
2205 if( dh_flag == 0 )
2206 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002207 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002208 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002209 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002210 goto cleanup;
2211
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002212 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002213 }
2214 }
2215 else
2216 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002217 /*
2218 * An necessary condition for Y and X = 2Y + 1 to be prime
2219 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2220 * Make sure it is satisfied, while keeping X = 3 mod 4
2221 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002222
2223 X->p[0] |= 2;
2224
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002225 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002226 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002227 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002228 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002229 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002230
2231 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002232 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2233 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002234
2235 while( 1 )
2236 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002237 /*
2238 * First, check small factors for X and Y
2239 * before doing Miller-Rabin on any of them
2240 */
2241 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2242 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2243 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2244 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002245 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002246 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002247 }
2248
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002249 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002250 goto cleanup;
2251
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002252 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002253 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002254 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2255 * so up Y by 6 and X by 12.
2256 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002257 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2258 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002259 }
2260 }
2261
2262cleanup:
2263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002265
2266 return( ret );
2267}
2268
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002269#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002270
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002271#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002272
Paul Bakker23986e52011-04-24 08:57:21 +00002273#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002274
2275static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2276{
2277 { 693, 609, 21 },
2278 { 1764, 868, 28 },
2279 { 768454923, 542167814, 1 }
2280};
2281
Paul Bakker5121ce52009-01-03 21:22:43 +00002282/*
2283 * Checkup routine
2284 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002285int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002286{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002287 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002289
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002290 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2291 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002293 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002294 "EFE021C2645FD1DC586E69184AF4A31E" \
2295 "D5F53E93B5F123FA41680867BA110131" \
2296 "944FE7952E2517337780CB0DB80E61AA" \
2297 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002300 "B2E7EFD37075B9F03FF989C7C5051C20" \
2301 "34D2A323810251127E7BF8625A4F49A5" \
2302 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2303 "5B5C25763222FEFCCFC38B832366C29E" ) );
2304
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002305 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002306 "0066A198186C18C10B2F5ED9B522752A" \
2307 "9830B69916E535C8F047518A889A43A5" \
2308 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2309
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002310 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002311
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002312 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002313 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2314 "9E857EA95A03512E2BAE7391688D264A" \
2315 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2316 "8001B72E848A38CAE1C65F78E56ABDEF" \
2317 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2318 "ECF677152EF804370C1A305CAF3B5BF1" \
2319 "30879B56C61DE584A0F53A2447A51E" ) );
2320
2321 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002322 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002324 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002325 {
2326 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002327 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002328
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002329 ret = 1;
2330 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002331 }
2332
2333 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002334 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002336 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002339 "256567336059E52CAE22925474705F39A94" ) );
2340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002342 "6613F26162223DF488E9CD48CC132C7A" \
2343 "0AC93C701B001B092E4E5B9F73BCD27B" \
2344 "9EE50D0657C77F374E903CDFA4C642" ) );
2345
2346 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002349 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2350 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002351 {
2352 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002354
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002355 ret = 1;
2356 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002357 }
2358
2359 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002360 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002361
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002362 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002363
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002364 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002365 "36E139AEA55215609D2816998ED020BB" \
2366 "BD96C37890F65171D948E9BC7CBAA4D9" \
2367 "325D24D6A3C12710F10A09FA08AB87" ) );
2368
2369 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002370 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002371
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002372 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002373 {
2374 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002375 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002376
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002377 ret = 1;
2378 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002379 }
2380
2381 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002382 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002383
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002384 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002385
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002386 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002387 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2388 "C3DBA76456363A10869622EAC2DD84EC" \
2389 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2390
2391 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002392 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002393
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002394 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002395 {
2396 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002397 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002398
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002399 ret = 1;
2400 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002401 }
2402
2403 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002404 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002405
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002406 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002407 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002408
Paul Bakker66d5d072014-06-17 16:39:18 +02002409 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002410 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002411 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2412 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002413
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002414 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002415
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002416 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002417 {
2418 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002419 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002420
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002421 ret = 1;
2422 goto cleanup;
2423 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002424 }
2425
2426 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002427 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002428
Paul Bakker5121ce52009-01-03 21:22:43 +00002429cleanup:
2430
2431 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002432 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2435 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002436
2437 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002438 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002439
2440 return( ret );
2441}
2442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002443#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002445#endif /* MBEDTLS_BIGNUM_C */