blob: 0e587f15ed9ab12afa814ebd4ecbee3383c975e5 [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 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200890 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000891 }
892
893 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200894 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200895
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000896 /*
897 * X should always be positive as a result of unsigned additions.
898 */
899 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000900
Paul Bakker23986e52011-04-24 08:57:21 +0000901 for( j = B->n; j > 0; j-- )
902 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000903 break;
904
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200905 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000906
907 o = B->p; p = X->p; c = 0;
908
Paul Bakker23986e52011-04-24 08:57:21 +0000909 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000910 {
911 *p += c; c = ( *p < c );
912 *p += *o; c += ( *p < *o );
913 }
914
915 while( c != 0 )
916 {
917 if( i >= X->n )
918 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000920 p = X->p + i;
921 }
922
Paul Bakker2d319fd2012-09-16 21:34:26 +0000923 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000924 }
925
926cleanup:
927
928 return( ret );
929}
930
931/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200932 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000933 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200934static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000935{
Paul Bakker23986e52011-04-24 08:57:21 +0000936 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200937 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000938
939 for( i = c = 0; i < n; i++, s++, d++ )
940 {
941 z = ( *d < c ); *d -= c;
942 c = ( *d < *s ) + z; *d -= *s;
943 }
944
945 while( c != 0 )
946 {
947 z = ( *d < c ); *d -= c;
948 c = z; i++; d++;
949 }
950}
951
952/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100953 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000954 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200955int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000956{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200957 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000958 int ret;
959 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000960
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200961 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
962 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000963
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200964 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000965
966 if( X == B )
967 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200968 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000969 B = &TB;
970 }
971
972 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200973 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000974
Paul Bakker1ef7a532009-06-20 10:50:55 +0000975 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100976 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000977 */
978 X->s = 1;
979
Paul Bakker5121ce52009-01-03 21:22:43 +0000980 ret = 0;
981
Paul Bakker23986e52011-04-24 08:57:21 +0000982 for( n = B->n; n > 0; n-- )
983 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000984 break;
985
Paul Bakker23986e52011-04-24 08:57:21 +0000986 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000987
988cleanup:
989
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200990 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000991
992 return( ret );
993}
994
995/*
996 * Signed addition: X = A + B
997 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200998int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000999{
1000 int ret, s = A->s;
1001
1002 if( A->s * B->s < 0 )
1003 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001004 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001005 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001006 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001007 X->s = s;
1008 }
1009 else
1010 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001011 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001012 X->s = -s;
1013 }
1014 }
1015 else
1016 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001017 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001018 X->s = s;
1019 }
1020
1021cleanup:
1022
1023 return( ret );
1024}
1025
1026/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001027 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001028 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001029int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001030{
1031 int ret, s = A->s;
1032
1033 if( A->s * B->s > 0 )
1034 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001035 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001036 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001037 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001038 X->s = s;
1039 }
1040 else
1041 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001043 X->s = -s;
1044 }
1045 }
1046 else
1047 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001048 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001049 X->s = s;
1050 }
1051
1052cleanup:
1053
1054 return( ret );
1055}
1056
1057/*
1058 * Signed addition: X = A + b
1059 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001060int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001061{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001062 mbedtls_mpi _B;
1063 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001064
1065 p[0] = ( b < 0 ) ? -b : b;
1066 _B.s = ( b < 0 ) ? -1 : 1;
1067 _B.n = 1;
1068 _B.p = p;
1069
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001070 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001071}
1072
1073/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001074 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001075 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001076int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001077{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001078 mbedtls_mpi _B;
1079 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001080
1081 p[0] = ( b < 0 ) ? -b : b;
1082 _B.s = ( b < 0 ) ? -1 : 1;
1083 _B.n = 1;
1084 _B.p = p;
1085
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001086 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001087}
1088
1089/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001090 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001091 */
1092static
1093#if defined(__APPLE__) && defined(__arm__)
1094/*
1095 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1096 * appears to need this to prevent bad ARM code generation at -O3.
1097 */
1098__attribute__ ((noinline))
1099#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001100void 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 +00001101{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001102 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001103
1104#if defined(MULADDC_HUIT)
1105 for( ; i >= 8; i -= 8 )
1106 {
1107 MULADDC_INIT
1108 MULADDC_HUIT
1109 MULADDC_STOP
1110 }
1111
1112 for( ; i > 0; i-- )
1113 {
1114 MULADDC_INIT
1115 MULADDC_CORE
1116 MULADDC_STOP
1117 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001118#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001119 for( ; i >= 16; i -= 16 )
1120 {
1121 MULADDC_INIT
1122 MULADDC_CORE MULADDC_CORE
1123 MULADDC_CORE MULADDC_CORE
1124 MULADDC_CORE MULADDC_CORE
1125 MULADDC_CORE MULADDC_CORE
1126
1127 MULADDC_CORE MULADDC_CORE
1128 MULADDC_CORE MULADDC_CORE
1129 MULADDC_CORE MULADDC_CORE
1130 MULADDC_CORE MULADDC_CORE
1131 MULADDC_STOP
1132 }
1133
1134 for( ; i >= 8; i -= 8 )
1135 {
1136 MULADDC_INIT
1137 MULADDC_CORE MULADDC_CORE
1138 MULADDC_CORE MULADDC_CORE
1139
1140 MULADDC_CORE MULADDC_CORE
1141 MULADDC_CORE MULADDC_CORE
1142 MULADDC_STOP
1143 }
1144
1145 for( ; i > 0; i-- )
1146 {
1147 MULADDC_INIT
1148 MULADDC_CORE
1149 MULADDC_STOP
1150 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001151#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001152
1153 t++;
1154
1155 do {
1156 *d += c; c = ( *d < c ); d++;
1157 }
1158 while( c != 0 );
1159}
1160
1161/*
1162 * Baseline multiplication: X = A * B (HAC 14.12)
1163 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001164int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001165{
Paul Bakker23986e52011-04-24 08:57:21 +00001166 int ret;
1167 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001168 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001170 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001171
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001172 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1173 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001174
Paul Bakker23986e52011-04-24 08:57:21 +00001175 for( i = A->n; i > 0; i-- )
1176 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001177 break;
1178
Paul Bakker23986e52011-04-24 08:57:21 +00001179 for( j = B->n; j > 0; j-- )
1180 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001181 break;
1182
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001183 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1184 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001185
Paul Bakker23986e52011-04-24 08:57:21 +00001186 for( i++; j > 0; j-- )
1187 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001188
1189 X->s = A->s * B->s;
1190
1191cleanup:
1192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001193 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001194
1195 return( ret );
1196}
1197
1198/*
1199 * Baseline multiplication: X = A * b
1200 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001201int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001202{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001203 mbedtls_mpi _B;
1204 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001205
1206 _B.s = 1;
1207 _B.n = 1;
1208 _B.p = p;
1209 p[0] = b;
1210
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001211 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001212}
1213
1214/*
Simon Butcher7ebe2782015-12-28 00:05:30 +00001215 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1216 * mbedtls_mpi_uint divisor, d
Simon Butcherea303e32015-11-26 23:43:34 +00001217 */
Simon Butcher7ebe2782015-12-28 00:05:30 +00001218static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1219 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcherea303e32015-11-26 23:43:34 +00001220{
Manuel Pégourié-Gonnard5a8396e2015-12-01 10:27:00 +01001221#if defined(MBEDTLS_HAVE_UDBL)
1222 mbedtls_t_udbl dividend, quotient;
Simon Butcher7ebe2782015-12-28 00:05:30 +00001223#else
Simon Butcher61891752016-01-03 00:24:34 +00001224 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1225 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcher7ebe2782015-12-28 00:05:30 +00001226 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1227 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher61891752016-01-03 00:24:34 +00001228 size_t s;
Manuel Pégourié-Gonnard5a8396e2015-12-01 10:27:00 +01001229#endif
1230
Simon Butcherea303e32015-11-26 23:43:34 +00001231 /*
1232 * Check for overflow
1233 */
Simon Butcher7ebe2782015-12-28 00:05:30 +00001234 if( 0 == d || u1 >= d )
Simon Butcherea303e32015-11-26 23:43:34 +00001235 {
Simon Butcher7ebe2782015-12-28 00:05:30 +00001236 if (r != NULL) *r = ~0;
Simon Butcherea303e32015-11-26 23:43:34 +00001237
Simon Butcher7ebe2782015-12-28 00:05:30 +00001238 return ( ~0 );
Simon Butcherea303e32015-11-26 23:43:34 +00001239 }
1240
1241#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcherea303e32015-11-26 23:43:34 +00001242 dividend = (mbedtls_t_udbl) u1 << biL;
1243 dividend |= (mbedtls_t_udbl) u0;
1244 quotient = dividend / d;
1245 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1246 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1247
1248 if( r != NULL )
Simon Butcher61891752016-01-03 00:24:34 +00001249 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcherea303e32015-11-26 23:43:34 +00001250
1251 return (mbedtls_mpi_uint) quotient;
1252#else
Simon Butcherea303e32015-11-26 23:43:34 +00001253
1254 /*
1255 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1256 * Vol. 2 - Seminumerical Algorithms, Knuth
1257 */
1258
1259 /*
1260 * Normalize the divisor, d, and dividend, u0, u1
1261 */
1262 s = mbedtls_clz( d );
1263 d = d << s;
1264
1265 u1 = u1 << s;
Simon Butcher61891752016-01-03 00:24:34 +00001266 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcherea303e32015-11-26 23:43:34 +00001267 u0 = u0 << s;
1268
1269 d1 = d >> biH;
Simon Butcher61891752016-01-03 00:24:34 +00001270 d0 = d & uint_halfword_mask;
Simon Butcherea303e32015-11-26 23:43:34 +00001271
1272 u0_msw = u0 >> biH;
Simon Butcher61891752016-01-03 00:24:34 +00001273 u0_lsw = u0 & uint_halfword_mask;
Simon Butcherea303e32015-11-26 23:43:34 +00001274
1275 /*
1276 * Find the first quotient and remainder
1277 */
1278 q1 = u1 / d1;
1279 r0 = u1 - d1 * q1;
1280
1281 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1282 {
1283 q1 -= 1;
1284 r0 += d1;
1285
1286 if ( r0 >= radix ) break;
1287 }
1288
Simon Butcher7ebe2782015-12-28 00:05:30 +00001289 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcherea303e32015-11-26 23:43:34 +00001290 q0 = rAX / d1;
1291 r0 = rAX - q0 * d1;
1292
1293 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1294 {
1295 q0 -= 1;
1296 r0 += d1;
1297
1298 if ( r0 >= radix ) break;
1299 }
1300
1301 if (r != NULL)
Simon Butcher7ebe2782015-12-28 00:05:30 +00001302 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcherea303e32015-11-26 23:43:34 +00001303
1304 quotient = q1 * radix + q0;
1305
1306 return quotient;
1307#endif
1308}
1309
1310/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001311 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001312 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001313int 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 +00001314{
Paul Bakker23986e52011-04-24 08:57:21 +00001315 int ret;
1316 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001317 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001319 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1320 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001321
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001322 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1323 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001324
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001325 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001326 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001327 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1328 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001329 return( 0 );
1330 }
1331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1333 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001334 X.s = Y.s = 1;
1335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1337 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1338 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1339 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001340
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001341 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001342 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001343 {
1344 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001345 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1346 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001347 }
1348 else k = 0;
1349
1350 n = X.n - 1;
1351 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001352 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001354 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001355 {
1356 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001357 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001358 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001359 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001360
1361 for( i = n; i > t ; i-- )
1362 {
1363 if( X.p[i] >= Y.p[t] )
1364 Z.p[i - t - 1] = ~0;
1365 else
1366 {
Simon Butcherea303e32015-11-26 23:43:34 +00001367 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1368 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001369 }
1370
1371 Z.p[i - t - 1]++;
1372 do
1373 {
1374 Z.p[i - t - 1]--;
1375
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001376 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001377 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001378 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001379 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001381 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001382 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1383 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001384 T2.p[2] = X.p[i];
1385 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001386 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001387
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001388 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1389 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1390 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001393 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001394 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1395 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1396 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001397 Z.p[i - t - 1]--;
1398 }
1399 }
1400
1401 if( Q != NULL )
1402 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001404 Q->s = A->s * B->s;
1405 }
1406
1407 if( R != NULL )
1408 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001409 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001410 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001411 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001413 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001414 R->s = 1;
1415 }
1416
1417cleanup:
1418
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001419 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1420 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001421
1422 return( ret );
1423}
1424
1425/*
1426 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001427 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001428int 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 +00001429{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001430 mbedtls_mpi _B;
1431 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001432
1433 p[0] = ( b < 0 ) ? -b : b;
1434 _B.s = ( b < 0 ) ? -1 : 1;
1435 _B.n = 1;
1436 _B.p = p;
1437
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001438 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001439}
1440
1441/*
1442 * Modulo: R = A mod B
1443 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001444int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001445{
1446 int ret;
1447
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001448 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1449 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001451 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001453 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1454 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001456 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1457 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001458
1459cleanup:
1460
1461 return( ret );
1462}
1463
1464/*
1465 * Modulo: r = A mod b
1466 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001467int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001468{
Paul Bakker23986e52011-04-24 08:57:21 +00001469 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001470 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001471
1472 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001473 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001474
1475 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001476 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001477
1478 /*
1479 * handle trivial cases
1480 */
1481 if( b == 1 )
1482 {
1483 *r = 0;
1484 return( 0 );
1485 }
1486
1487 if( b == 2 )
1488 {
1489 *r = A->p[0] & 1;
1490 return( 0 );
1491 }
1492
1493 /*
1494 * general case
1495 */
Paul Bakker23986e52011-04-24 08:57:21 +00001496 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001497 {
Paul Bakker23986e52011-04-24 08:57:21 +00001498 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001499 y = ( y << biH ) | ( x >> biH );
1500 z = y / b;
1501 y -= z * b;
1502
1503 x <<= biH;
1504 y = ( y << biH ) | ( x >> biH );
1505 z = y / b;
1506 y -= z * b;
1507 }
1508
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001509 /*
1510 * If A is negative, then the current y represents a negative value.
1511 * Flipping it to the positive side.
1512 */
1513 if( A->s < 0 && y != 0 )
1514 y = b - y;
1515
Paul Bakker5121ce52009-01-03 21:22:43 +00001516 *r = y;
1517
1518 return( 0 );
1519}
1520
1521/*
1522 * Fast Montgomery initialization (thanks to Tom St Denis)
1523 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001524static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001525{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001526 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001527 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001528
1529 x = m0;
1530 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001531
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001532 for( i = biL; i >= 8; i /= 2 )
1533 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001534
1535 *mm = ~x + 1;
1536}
1537
1538/*
1539 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1540 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001541static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1542 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001543{
Paul Bakker23986e52011-04-24 08:57:21 +00001544 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001545 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001546
1547 memset( T->p, 0, T->n * ciL );
1548
1549 d = T->p;
1550 n = N->n;
1551 m = ( B->n < n ) ? B->n : n;
1552
1553 for( i = 0; i < n; i++ )
1554 {
1555 /*
1556 * T = (T + u0*B + u1*N) / 2^biL
1557 */
1558 u0 = A->p[i];
1559 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1560
1561 mpi_mul_hlp( m, B->p, d, u0 );
1562 mpi_mul_hlp( n, N->p, d, u1 );
1563
1564 *d++ = u0; d[n + 1] = 0;
1565 }
1566
Paul Bakker66d5d072014-06-17 16:39:18 +02001567 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001568
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001569 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001570 mpi_sub_hlp( n, N->p, A->p );
1571 else
1572 /* prevent timing attacks */
1573 mpi_sub_hlp( n, A->p, T->p );
1574}
1575
1576/*
1577 * Montgomery reduction: A = A * R^-1 mod N
1578 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001579static 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 +00001580{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001581 mbedtls_mpi_uint z = 1;
1582 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001583
Paul Bakker8ddb6452013-02-27 14:56:33 +01001584 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001585 U.p = &z;
1586
1587 mpi_montmul( A, &U, N, mm, T );
1588}
1589
1590/*
1591 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1592 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001593int 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 +00001594{
Paul Bakker23986e52011-04-24 08:57:21 +00001595 int ret;
1596 size_t wbits, wsize, one = 1;
1597 size_t i, j, nblimbs;
1598 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001599 mbedtls_mpi_uint ei, mm, state;
1600 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001601 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001602
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001603 if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
1604 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001605
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001606 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1607 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001608
1609 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001610 * Init temps and window size
1611 */
1612 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001613 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1614 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001615 memset( W, 0, sizeof( W ) );
1616
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001617 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001618
1619 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1620 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001622 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1623 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001624
Paul Bakker5121ce52009-01-03 21:22:43 +00001625 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001626 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1627 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1628 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001629
1630 /*
Paul Bakker50546922012-05-19 08:40:49 +00001631 * Compensate for negative A (and correct at the end)
1632 */
1633 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001634 if( neg )
1635 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001637 Apos.s = 1;
1638 A = &Apos;
1639 }
1640
1641 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001642 * If 1st call, pre-compute R^2 mod N
1643 */
1644 if( _RR == NULL || _RR->p == NULL )
1645 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001646 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1647 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1648 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001649
1650 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001652 }
1653 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001654 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001655
1656 /*
1657 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1658 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001659 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1660 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001661 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001662 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001663
1664 mpi_montmul( &W[1], &RR, N, mm, &T );
1665
1666 /*
1667 * X = R^2 * R^-1 mod N = R mod N
1668 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001669 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001670 mpi_montred( X, N, mm, &T );
1671
1672 if( wsize > 1 )
1673 {
1674 /*
1675 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1676 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001677 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001678
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001679 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1680 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001681
1682 for( i = 0; i < wsize - 1; i++ )
1683 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001684
Paul Bakker5121ce52009-01-03 21:22:43 +00001685 /*
1686 * W[i] = W[i - 1] * W[1]
1687 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001688 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001689 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001690 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1691 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001692
1693 mpi_montmul( &W[i], &W[1], N, mm, &T );
1694 }
1695 }
1696
1697 nblimbs = E->n;
1698 bufsize = 0;
1699 nbits = 0;
1700 wbits = 0;
1701 state = 0;
1702
1703 while( 1 )
1704 {
1705 if( bufsize == 0 )
1706 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001707 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001708 break;
1709
Paul Bakker0d7702c2013-10-29 16:18:35 +01001710 nblimbs--;
1711
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001712 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001713 }
1714
1715 bufsize--;
1716
1717 ei = (E->p[nblimbs] >> bufsize) & 1;
1718
1719 /*
1720 * skip leading 0s
1721 */
1722 if( ei == 0 && state == 0 )
1723 continue;
1724
1725 if( ei == 0 && state == 1 )
1726 {
1727 /*
1728 * out of window, square X
1729 */
1730 mpi_montmul( X, X, N, mm, &T );
1731 continue;
1732 }
1733
1734 /*
1735 * add ei to current window
1736 */
1737 state = 2;
1738
1739 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001740 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001741
1742 if( nbits == wsize )
1743 {
1744 /*
1745 * X = X^wsize R^-1 mod N
1746 */
1747 for( i = 0; i < wsize; i++ )
1748 mpi_montmul( X, X, N, mm, &T );
1749
1750 /*
1751 * X = X * W[wbits] R^-1 mod N
1752 */
1753 mpi_montmul( X, &W[wbits], N, mm, &T );
1754
1755 state--;
1756 nbits = 0;
1757 wbits = 0;
1758 }
1759 }
1760
1761 /*
1762 * process the remaining bits
1763 */
1764 for( i = 0; i < nbits; i++ )
1765 {
1766 mpi_montmul( X, X, N, mm, &T );
1767
1768 wbits <<= 1;
1769
Paul Bakker66d5d072014-06-17 16:39:18 +02001770 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001771 mpi_montmul( X, &W[1], N, mm, &T );
1772 }
1773
1774 /*
1775 * X = A^E * R * R^-1 mod N = A^E mod N
1776 */
1777 mpi_montred( X, N, mm, &T );
1778
Paul Bakkerf6198c12012-05-16 08:02:29 +00001779 if( neg )
1780 {
1781 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001782 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001783 }
1784
Paul Bakker5121ce52009-01-03 21:22:43 +00001785cleanup:
1786
Paul Bakker66d5d072014-06-17 16:39:18 +02001787 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001788 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001789
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001790 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001791
Paul Bakker75a28602014-03-31 12:08:17 +02001792 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001793 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001794
1795 return( ret );
1796}
1797
Paul Bakker5121ce52009-01-03 21:22:43 +00001798/*
1799 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1800 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001801int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001802{
Paul Bakker23986e52011-04-24 08:57:21 +00001803 int ret;
1804 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001805 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001806
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001807 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001808
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001809 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1810 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001811
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001812 lz = mbedtls_mpi_lsb( &TA );
1813 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001814
Paul Bakker66d5d072014-06-17 16:39:18 +02001815 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001816 lz = lzt;
1817
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001818 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1819 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001820
Paul Bakker5121ce52009-01-03 21:22:43 +00001821 TA.s = TB.s = 1;
1822
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001823 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001824 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001825 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1826 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001827
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001828 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001829 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1831 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001832 }
1833 else
1834 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001835 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1836 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001837 }
1838 }
1839
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001840 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1841 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001842
1843cleanup:
1844
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001845 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846
1847 return( ret );
1848}
1849
Paul Bakker33dc46b2014-04-30 16:11:39 +02001850/*
1851 * Fill X with size bytes of random.
1852 *
1853 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001854 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001855 * deterministic, eg for tests).
1856 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001857int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001858 int (*f_rng)(void *, unsigned char *, size_t),
1859 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001860{
Paul Bakker23986e52011-04-24 08:57:21 +00001861 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001862 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001863
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001864 if( size > MBEDTLS_MPI_MAX_SIZE )
1865 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001866
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001867 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1868 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001869
1870cleanup:
1871 return( ret );
1872}
1873
Paul Bakker5121ce52009-01-03 21:22:43 +00001874/*
1875 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1876 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001877int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001878{
1879 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001881
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 )
1883 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001884
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001885 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1886 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1887 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001888
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001889 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001890
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001891 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001892 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001893 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001894 goto cleanup;
1895 }
1896
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001897 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1898 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1899 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1900 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001901
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001902 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1903 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1904 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1905 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001906
1907 do
1908 {
1909 while( ( TU.p[0] & 1 ) == 0 )
1910 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001911 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001912
1913 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1914 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001915 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1916 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001917 }
1918
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001919 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1920 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001921 }
1922
1923 while( ( TV.p[0] & 1 ) == 0 )
1924 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001925 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001926
1927 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1928 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1930 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001931 }
1932
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001933 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1934 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001935 }
1936
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001937 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001938 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001939 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1940 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1941 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001942 }
1943 else
1944 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001945 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1946 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1947 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001948 }
1949 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001950 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001951
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001952 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1953 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001954
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001955 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1956 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001957
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001958 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001959
1960cleanup:
1961
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001962 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1963 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1964 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001965
1966 return( ret );
1967}
1968
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001969#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001970
Paul Bakker5121ce52009-01-03 21:22:43 +00001971static const int small_prime[] =
1972{
1973 3, 5, 7, 11, 13, 17, 19, 23,
1974 29, 31, 37, 41, 43, 47, 53, 59,
1975 61, 67, 71, 73, 79, 83, 89, 97,
1976 101, 103, 107, 109, 113, 127, 131, 137,
1977 139, 149, 151, 157, 163, 167, 173, 179,
1978 181, 191, 193, 197, 199, 211, 223, 227,
1979 229, 233, 239, 241, 251, 257, 263, 269,
1980 271, 277, 281, 283, 293, 307, 311, 313,
1981 317, 331, 337, 347, 349, 353, 359, 367,
1982 373, 379, 383, 389, 397, 401, 409, 419,
1983 421, 431, 433, 439, 443, 449, 457, 461,
1984 463, 467, 479, 487, 491, 499, 503, 509,
1985 521, 523, 541, 547, 557, 563, 569, 571,
1986 577, 587, 593, 599, 601, 607, 613, 617,
1987 619, 631, 641, 643, 647, 653, 659, 661,
1988 673, 677, 683, 691, 701, 709, 719, 727,
1989 733, 739, 743, 751, 757, 761, 769, 773,
1990 787, 797, 809, 811, 821, 823, 827, 829,
1991 839, 853, 857, 859, 863, 877, 881, 883,
1992 887, 907, 911, 919, 929, 937, 941, 947,
1993 953, 967, 971, 977, 983, 991, 997, -103
1994};
1995
1996/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001997 * Small divisors test (X must be positive)
1998 *
1999 * Return values:
2000 * 0: no small factor (possible prime, more tests needed)
2001 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002002 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002003 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002004 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002005static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002006{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002007 int ret = 0;
2008 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002009 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002010
Paul Bakker5121ce52009-01-03 21:22:43 +00002011 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002012 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002013
2014 for( i = 0; small_prime[i] > 0; i++ )
2015 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002017 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002018
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002019 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002020
2021 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002022 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002023 }
2024
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002025cleanup:
2026 return( ret );
2027}
2028
2029/*
2030 * Miller-Rabin pseudo-primality test (HAC 4.24)
2031 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002032static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002033 int (*f_rng)(void *, unsigned char *, size_t),
2034 void *p_rng )
2035{
Pascal Junodb99183d2015-03-11 16:49:45 +01002036 int ret, count;
2037 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002038 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002039
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002040 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2041 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002042
Paul Bakker5121ce52009-01-03 21:22:43 +00002043 /*
2044 * W = |X| - 1
2045 * R = W >> lsb( W )
2046 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002047 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2048 s = mbedtls_mpi_lsb( &W );
2049 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2050 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002051
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002052 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002053 /*
2054 * HAC, table 4.4
2055 */
2056 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2057 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2058 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2059
2060 for( i = 0; i < n; i++ )
2061 {
2062 /*
2063 * pick a random A, 1 < A < |X| - 1
2064 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002065 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002066
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002067 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00002068 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002069 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002070 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00002071 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002072 A.p[0] |= 3;
2073
Pascal Junodb99183d2015-03-11 16:49:45 +01002074 count = 0;
2075 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002076 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002077
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002078 j = mbedtls_mpi_bitlen( &A );
2079 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002080 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002081 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002082 }
2083
2084 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002085 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002086 }
2087
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002088 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2089 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002090
2091 /*
2092 * A = A^R mod |X|
2093 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002094 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002095
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002096 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2097 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002098 continue;
2099
2100 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002101 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002102 {
2103 /*
2104 * A = A * A mod |X|
2105 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002106 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2107 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002108
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002109 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002110 break;
2111
2112 j++;
2113 }
2114
2115 /*
2116 * not prime if A != |X| - 1 or A == 1
2117 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002118 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2119 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002120 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002121 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002122 break;
2123 }
2124 }
2125
2126cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002127 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2128 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002129
2130 return( ret );
2131}
2132
2133/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002134 * Pseudo-primality test: small factors, then Miller-Rabin
2135 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002136int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002137 int (*f_rng)(void *, unsigned char *, size_t),
2138 void *p_rng )
2139{
2140 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002141 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002142
2143 XX.s = 1;
2144 XX.n = X->n;
2145 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002146
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002147 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2148 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2149 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002150
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002151 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002152 return( 0 );
2153
2154 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2155 {
2156 if( ret == 1 )
2157 return( 0 );
2158
2159 return( ret );
2160 }
2161
2162 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2163}
2164
2165/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002166 * Prime number generation
2167 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002168int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002169 int (*f_rng)(void *, unsigned char *, size_t),
2170 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002171{
Paul Bakker23986e52011-04-24 08:57:21 +00002172 int ret;
2173 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002174 mbedtls_mpi_uint r;
2175 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2178 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002180 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002181
2182 n = BITS_TO_LIMBS( nbits );
2183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002185
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002186 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002187 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002188
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002189 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002190
2191 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002192
2193 if( dh_flag == 0 )
2194 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002195 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002196 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002197 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002198 goto cleanup;
2199
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002200 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002201 }
2202 }
2203 else
2204 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002205 /*
2206 * An necessary condition for Y and X = 2Y + 1 to be prime
2207 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2208 * Make sure it is satisfied, while keeping X = 3 mod 4
2209 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002210
2211 X->p[0] |= 2;
2212
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002213 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002214 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002215 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002216 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002217 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002218
2219 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002220 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2221 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002222
2223 while( 1 )
2224 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002225 /*
2226 * First, check small factors for X and Y
2227 * before doing Miller-Rabin on any of them
2228 */
2229 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2230 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2231 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2232 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002233 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002234 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002235 }
2236
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002237 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002238 goto cleanup;
2239
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002240 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002241 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002242 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2243 * so up Y by 6 and X by 12.
2244 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002245 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2246 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002247 }
2248 }
2249
2250cleanup:
2251
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002252 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002253
2254 return( ret );
2255}
2256
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002257#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002259#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002260
Paul Bakker23986e52011-04-24 08:57:21 +00002261#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002262
2263static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2264{
2265 { 693, 609, 21 },
2266 { 1764, 868, 28 },
2267 { 768454923, 542167814, 1 }
2268};
2269
Paul Bakker5121ce52009-01-03 21:22:43 +00002270/*
2271 * Checkup routine
2272 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002273int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002274{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002275 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002276 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002277
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002278 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2279 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002280
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002281 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002282 "EFE021C2645FD1DC586E69184AF4A31E" \
2283 "D5F53E93B5F123FA41680867BA110131" \
2284 "944FE7952E2517337780CB0DB80E61AA" \
2285 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002287 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002288 "B2E7EFD37075B9F03FF989C7C5051C20" \
2289 "34D2A323810251127E7BF8625A4F49A5" \
2290 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2291 "5B5C25763222FEFCCFC38B832366C29E" ) );
2292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002293 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002294 "0066A198186C18C10B2F5ED9B522752A" \
2295 "9830B69916E535C8F047518A889A43A5" \
2296 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2297
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002298 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002299
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002300 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002301 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2302 "9E857EA95A03512E2BAE7391688D264A" \
2303 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2304 "8001B72E848A38CAE1C65F78E56ABDEF" \
2305 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2306 "ECF677152EF804370C1A305CAF3B5BF1" \
2307 "30879B56C61DE584A0F53A2447A51E" ) );
2308
2309 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002310 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002311
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002312 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002313 {
2314 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002315 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002316
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002317 ret = 1;
2318 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002319 }
2320
2321 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002322 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002324 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002326 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002327 "256567336059E52CAE22925474705F39A94" ) );
2328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002329 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002330 "6613F26162223DF488E9CD48CC132C7A" \
2331 "0AC93C701B001B092E4E5B9F73BCD27B" \
2332 "9EE50D0657C77F374E903CDFA4C642" ) );
2333
2334 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002336
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002337 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2338 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002339 {
2340 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002342
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002343 ret = 1;
2344 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002345 }
2346
2347 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002348 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002349
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002350 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002351
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002352 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002353 "36E139AEA55215609D2816998ED020BB" \
2354 "BD96C37890F65171D948E9BC7CBAA4D9" \
2355 "325D24D6A3C12710F10A09FA08AB87" ) );
2356
2357 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002358 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002359
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002360 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002361 {
2362 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002363 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002364
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002365 ret = 1;
2366 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002367 }
2368
2369 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002370 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002371
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002372 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002373
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002374 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002375 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2376 "C3DBA76456363A10869622EAC2DD84EC" \
2377 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2378
2379 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002380 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002381
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002382 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002383 {
2384 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002386
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002387 ret = 1;
2388 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002389 }
2390
2391 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002392 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002393
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002394 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002395 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002396
Paul Bakker66d5d072014-06-17 16:39:18 +02002397 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002398 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002399 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2400 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002401
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002402 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002403
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002404 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002405 {
2406 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002407 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002408
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002409 ret = 1;
2410 goto cleanup;
2411 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002412 }
2413
2414 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002415 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002416
Paul Bakker5121ce52009-01-03 21:22:43 +00002417cleanup:
2418
2419 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002420 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002421
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002422 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2423 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002424
2425 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002426 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002427
2428 return( ret );
2429}
2430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002431#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002432
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002433#endif /* MBEDTLS_BIGNUM_C */