blob: d8b842fa3c03025bf060cdf1427ab6d9f0925277 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcherea303e32015-11-26 23:43:34 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcherea303e32015-11-26 23:43:34 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcherea303e32015-11-26 23:43:34 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcher7ebe2782015-12-28 00:05:30 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000048
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <string.h>
50
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000052#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020053#else
Rich Evans00ab4702015-02-06 13:43:58 +000054#include <stdio.h>
55#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020057#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020059#endif
60
Paul Bakker34617722014-06-13 17:20:13 +020061/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020062static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020063 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
64}
65
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020066#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000067#define biL (ciL << 3) /* bits in limb */
68#define biH (ciL << 2) /* half limb size */
69
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010070#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
71
Paul Bakker5121ce52009-01-03 21:22:43 +000072/*
73 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020074 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000075 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020076#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
77#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000078
79/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000080 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000081 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000083{
Paul Bakker6c591fa2011-05-05 11:49:20 +000084 if( X == NULL )
85 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000086
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 X->s = 1;
88 X->n = 0;
89 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000090}
91
92/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000094 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020095void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000096{
Paul Bakker6c591fa2011-05-05 11:49:20 +000097 if( X == NULL )
98 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000099
Paul Bakker6c591fa2011-05-05 11:49:20 +0000100 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000101 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200102 mbedtls_zeroize( X->p, X->n * ciL );
103 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000104 }
105
Paul Bakker6c591fa2011-05-05 11:49:20 +0000106 X->s = 1;
107 X->n = 0;
108 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000109}
110
111/*
112 * Enlarge to the specified number of limbs
113 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200114int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000115{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000117
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200118 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200119 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000120
Paul Bakker5121ce52009-01-03 21:22:43 +0000121 if( X->n < nblimbs )
122 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200123 if( ( p = mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200124 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000125
Paul Bakker5121ce52009-01-03 21:22:43 +0000126 if( X->p != NULL )
127 {
128 memcpy( p, X->p, X->n * ciL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 mbedtls_zeroize( X->p, X->n * ciL );
130 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000131 }
132
133 X->n = nblimbs;
134 X->p = p;
135 }
136
137 return( 0 );
138}
139
140/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100141 * Resize down as much as possible,
142 * while keeping at least the specified number of limbs
143 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100145{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100147 size_t i;
148
149 /* Actually resize up in this case */
150 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152
153 for( i = X->n - 1; i > 0; i-- )
154 if( X->p[i] != 0 )
155 break;
156 i++;
157
158 if( i < nblimbs )
159 i = nblimbs;
160
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200161 if( ( p = mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200162 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100164 if( X->p != NULL )
165 {
166 memcpy( p, X->p, i * ciL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200167 mbedtls_zeroize( X->p, X->n * ciL );
168 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100169 }
170
171 X->n = i;
172 X->p = p;
173
174 return( 0 );
175}
176
177/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000178 * Copy the contents of Y into X
179 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000181{
Paul Bakker23986e52011-04-24 08:57:21 +0000182 int ret;
183 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000184
185 if( X == Y )
186 return( 0 );
187
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200188 if( Y->p == NULL )
189 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200191 return( 0 );
192 }
193
Paul Bakker5121ce52009-01-03 21:22:43 +0000194 for( i = Y->n - 1; i > 0; i-- )
195 if( Y->p[i] != 0 )
196 break;
197 i++;
198
199 X->s = Y->s;
200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200201 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000202
203 memset( X->p, 0, X->n * ciL );
204 memcpy( X->p, Y->p, i * ciL );
205
206cleanup:
207
208 return( ret );
209}
210
211/*
212 * Swap the contents of X and Y
213 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200214void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000215{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218 memcpy( &T, X, sizeof( mbedtls_mpi ) );
219 memcpy( X, Y, sizeof( mbedtls_mpi ) );
220 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000221}
222
223/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100224 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100225 * about whether the assignment was made or not.
226 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100227 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100229{
230 int ret = 0;
231 size_t i;
232
Pascal Junodb99183d2015-03-11 16:49:45 +0100233 /* make sure assign is 0 or 1 in a time-constant manner */
234 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100235
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100237
Paul Bakker66d5d072014-06-17 16:39:18 +0200238 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100239
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100240 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200241 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100242
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100243 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200244 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100245
246cleanup:
247 return( ret );
248}
249
250/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100251 * Conditionally swap X and Y, without leaking information
252 * about whether the swap was made or not.
253 * Here it is not ok to simply swap the pointers, which whould lead to
254 * different memory access patterns when X and Y are used afterwards.
255 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100257{
258 int ret, s;
259 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100261
262 if( X == Y )
263 return( 0 );
264
Pascal Junodb99183d2015-03-11 16:49:45 +0100265 /* make sure swap is 0 or 1 in a time-constant manner */
266 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
269 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100270
271 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200272 X->s = X->s * ( 1 - swap ) + Y->s * swap;
273 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274
275
276 for( i = 0; i < X->n; i++ )
277 {
278 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200279 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
280 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100281 }
282
283cleanup:
284 return( ret );
285}
286
287/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000288 * Set value from integer
289 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200290int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000291{
292 int ret;
293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000295 memset( X->p, 0, X->n * ciL );
296
297 X->p[0] = ( z < 0 ) ? -z : z;
298 X->s = ( z < 0 ) ? -1 : 1;
299
300cleanup:
301
302 return( ret );
303}
304
305/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000306 * Get a specific bit
307 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000309{
310 if( X->n * biL <= pos )
311 return( 0 );
312
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200313 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000314}
315
316/*
317 * Set a bit to a specific value of 0 or 1
318 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200319int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000320{
321 int ret = 0;
322 size_t off = pos / biL;
323 size_t idx = pos % biL;
324
325 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200327
Paul Bakker2f5947e2011-05-18 15:47:11 +0000328 if( X->n * biL <= pos )
329 {
330 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200331 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200333 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000334 }
335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
337 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338
339cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200340
Paul Bakker2f5947e2011-05-18 15:47:11 +0000341 return( ret );
342}
343
344/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200345 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000346 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000348{
Paul Bakker23986e52011-04-24 08:57:21 +0000349 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000350
351 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000352 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000353 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
354 return( count );
355
356 return( 0 );
357}
358
359/*
Simon Butcherea303e32015-11-26 23:43:34 +0000360 * Count leading zero bits in a given integer
361 */
362static size_t mbedtls_clz( const mbedtls_mpi_uint x )
363{
364 size_t j;
Manuel Pégourié-Gonnard3eab29a2015-12-01 09:31:52 +0100365 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcherea303e32015-11-26 23:43:34 +0000366
367 for( j = 0; j < biL; j++ )
368 {
369 if( x & mask ) break;
370
371 mask >>= 1;
372 }
373
374 return j;
375}
376
377/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200378 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200380size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000381{
Paul Bakker23986e52011-04-24 08:57:21 +0000382 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000383
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200384 if( X->n == 0 )
385 return( 0 );
386
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 for( i = X->n - 1; i > 0; i-- )
388 if( X->p[i] != 0 )
389 break;
390
Simon Butcherea303e32015-11-26 23:43:34 +0000391 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000392
Paul Bakker23986e52011-04-24 08:57:21 +0000393 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000394}
395
396/*
397 * Return the total size in bytes
398 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000400{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200401 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000402}
403
404/*
405 * Convert an ASCII character to digit value
406 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000408{
409 *d = 255;
410
411 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
412 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
413 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
414
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415 if( *d >= (mbedtls_mpi_uint) radix )
416 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
418 return( 0 );
419}
420
421/*
422 * Import from an ASCII string
423 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000425{
Paul Bakker23986e52011-04-24 08:57:21 +0000426 int ret;
427 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 mbedtls_mpi_uint d;
429 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000430
431 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000435
Paul Bakkerff60ee62010-03-16 21:09:09 +0000436 slen = strlen( s );
437
Paul Bakker5121ce52009-01-03 21:22:43 +0000438 if( radix == 16 )
439 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100440 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200441 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
442
Paul Bakkerff60ee62010-03-16 21:09:09 +0000443 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
446 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000447
Paul Bakker23986e52011-04-24 08:57:21 +0000448 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000449 {
Paul Bakker23986e52011-04-24 08:57:21 +0000450 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000451 {
452 X->s = -1;
453 break;
454 }
455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200457 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 }
459 }
460 else
461 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000463
Paul Bakkerff60ee62010-03-16 21:09:09 +0000464 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000465 {
466 if( i == 0 && s[i] == '-' )
467 {
468 X->s = -1;
469 continue;
470 }
471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
473 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000474
475 if( X->s == 1 )
476 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000478 }
479 else
480 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000482 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000483 }
484 }
485
486cleanup:
487
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200488 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000489
490 return( ret );
491}
492
493/*
494 * Helper to write the digits high-order first
495 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000497{
498 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000500
501 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
505 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
508 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000509
510 if( r < 10 )
511 *(*p)++ = (char)( r + 0x30 );
512 else
513 *(*p)++ = (char)( r + 0x37 );
514
515cleanup:
516
517 return( ret );
518}
519
520/*
521 * Export into an ASCII string
522 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100523int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
524 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000525{
Paul Bakker23986e52011-04-24 08:57:21 +0000526 int ret = 0;
527 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000528 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000530
531 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000533
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200534 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000535 if( radix >= 4 ) n >>= 1;
536 if( radix >= 16 ) n >>= 1;
537 n += 3;
538
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100539 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000540 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100541 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000543 }
544
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100545 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000547
548 if( X->s == -1 )
549 *p++ = '-';
550
551 if( radix == 16 )
552 {
Paul Bakker23986e52011-04-24 08:57:21 +0000553 int c;
554 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000555
Paul Bakker23986e52011-04-24 08:57:21 +0000556 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000557 {
Paul Bakker23986e52011-04-24 08:57:21 +0000558 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000559 {
Paul Bakker23986e52011-04-24 08:57:21 +0000560 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000561
Paul Bakker6c343d72014-07-10 14:36:19 +0200562 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000563 continue;
564
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000565 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000566 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000567 k = 1;
568 }
569 }
570 }
571 else
572 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000574
575 if( T.s == -1 )
576 T.s = 1;
577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000579 }
580
581 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100582 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000583
584cleanup:
585
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000587
588 return( ret );
589}
590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000592/*
593 * Read X from an opened file
594 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200595int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000596{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000598 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000599 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000600 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000601 * Buffer should have space for (short) label and decimal formatted MPI,
602 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000603 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000605
606 memset( s, 0, sizeof( s ) );
607 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000609
610 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000611 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000613
Paul Bakker5121ce52009-01-03 21:22:43 +0000614 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
615 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
616
617 p = s + slen;
618 while( --p >= s )
619 if( mpi_get_digit( &d, radix, *p ) != 0 )
620 break;
621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000623}
624
625/*
626 * Write X into an opened file (or stdout if fout == NULL)
627 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000629{
Paul Bakker23986e52011-04-24 08:57:21 +0000630 int ret;
631 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000632 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000633 * Buffer should have space for (short) label and decimal formatted MPI,
634 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000635 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200636 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000637
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100638 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000639
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100640 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000641
642 if( p == NULL ) p = "";
643
644 plen = strlen( p );
645 slen = strlen( s );
646 s[slen++] = '\r';
647 s[slen++] = '\n';
648
649 if( fout != NULL )
650 {
651 if( fwrite( p, 1, plen, fout ) != plen ||
652 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000654 }
655 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000657
658cleanup:
659
660 return( ret );
661}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000663
664/*
665 * Import X from unsigned binary data, big endian
666 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000668{
Paul Bakker23986e52011-04-24 08:57:21 +0000669 int ret;
670 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000671
672 for( n = 0; n < buflen; n++ )
673 if( buf[n] != 0 )
674 break;
675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
677 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000678
Paul Bakker23986e52011-04-24 08:57:21 +0000679 for( i = buflen, j = 0; i > n; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000681
682cleanup:
683
684 return( ret );
685}
686
687/*
688 * Export X into unsigned binary data, big endian
689 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000691{
Paul Bakker23986e52011-04-24 08:57:21 +0000692 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000693
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200694 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000695
696 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
699 memset( buf, 0, buflen );
700
701 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
702 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
703
704 return( 0 );
705}
706
707/*
708 * Left-shift: X <<= count
709 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000711{
Paul Bakker23986e52011-04-24 08:57:21 +0000712 int ret;
713 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000715
716 v0 = count / (biL );
717 t1 = count & (biL - 1);
718
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200719 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000720
Paul Bakkerf9688572011-05-05 10:00:45 +0000721 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000723
724 ret = 0;
725
726 /*
727 * shift by count / limb_size
728 */
729 if( v0 > 0 )
730 {
Paul Bakker23986e52011-04-24 08:57:21 +0000731 for( i = X->n; i > v0; i-- )
732 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000733
Paul Bakker23986e52011-04-24 08:57:21 +0000734 for( ; i > 0; i-- )
735 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000736 }
737
738 /*
739 * shift by count % limb_size
740 */
741 if( t1 > 0 )
742 {
743 for( i = v0; i < X->n; i++ )
744 {
745 r1 = X->p[i] >> (biL - t1);
746 X->p[i] <<= t1;
747 X->p[i] |= r0;
748 r0 = r1;
749 }
750 }
751
752cleanup:
753
754 return( ret );
755}
756
757/*
758 * Right-shift: X >>= count
759 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200760int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000761{
Paul Bakker23986e52011-04-24 08:57:21 +0000762 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200763 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000764
765 v0 = count / biL;
766 v1 = count & (biL - 1);
767
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100768 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200769 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100770
Paul Bakker5121ce52009-01-03 21:22:43 +0000771 /*
772 * shift by count / limb_size
773 */
774 if( v0 > 0 )
775 {
776 for( i = 0; i < X->n - v0; i++ )
777 X->p[i] = X->p[i + v0];
778
779 for( ; i < X->n; i++ )
780 X->p[i] = 0;
781 }
782
783 /*
784 * shift by count % limb_size
785 */
786 if( v1 > 0 )
787 {
Paul Bakker23986e52011-04-24 08:57:21 +0000788 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000789 {
Paul Bakker23986e52011-04-24 08:57:21 +0000790 r1 = X->p[i - 1] << (biL - v1);
791 X->p[i - 1] >>= v1;
792 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000793 r0 = r1;
794 }
795 }
796
797 return( 0 );
798}
799
800/*
801 * Compare unsigned values
802 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200803int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000804{
Paul Bakker23986e52011-04-24 08:57:21 +0000805 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000806
Paul Bakker23986e52011-04-24 08:57:21 +0000807 for( i = X->n; i > 0; i-- )
808 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000809 break;
810
Paul Bakker23986e52011-04-24 08:57:21 +0000811 for( j = Y->n; j > 0; j-- )
812 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000813 break;
814
Paul Bakker23986e52011-04-24 08:57:21 +0000815 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000816 return( 0 );
817
818 if( i > j ) return( 1 );
819 if( j > i ) return( -1 );
820
Paul Bakker23986e52011-04-24 08:57:21 +0000821 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000822 {
Paul Bakker23986e52011-04-24 08:57:21 +0000823 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
824 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000825 }
826
827 return( 0 );
828}
829
830/*
831 * Compare signed values
832 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200833int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000834{
Paul Bakker23986e52011-04-24 08:57:21 +0000835 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000836
Paul Bakker23986e52011-04-24 08:57:21 +0000837 for( i = X->n; i > 0; i-- )
838 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000839 break;
840
Paul Bakker23986e52011-04-24 08:57:21 +0000841 for( j = Y->n; j > 0; j-- )
842 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000843 break;
844
Paul Bakker23986e52011-04-24 08:57:21 +0000845 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000846 return( 0 );
847
848 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000849 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000850
851 if( X->s > 0 && Y->s < 0 ) return( 1 );
852 if( Y->s > 0 && X->s < 0 ) return( -1 );
853
Paul Bakker23986e52011-04-24 08:57:21 +0000854 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000855 {
Paul Bakker23986e52011-04-24 08:57:21 +0000856 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
857 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000858 }
859
860 return( 0 );
861}
862
863/*
864 * Compare signed values
865 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200866int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000867{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200868 mbedtls_mpi Y;
869 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000870
871 *p = ( z < 0 ) ? -z : z;
872 Y.s = ( z < 0 ) ? -1 : 1;
873 Y.n = 1;
874 Y.p = p;
875
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200876 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000877}
878
879/*
880 * Unsigned addition: X = |A| + |B| (HAC 14.7)
881 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200882int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000883{
Paul Bakker23986e52011-04-24 08:57:21 +0000884 int ret;
885 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200886 mbedtls_mpi_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000887
888 if( X == B )
889 {
Janos Follathd0e0c032015-10-25 10:58:03 +0100890 const mbedtls_mpi *T;
891
892 if( B == A)
893 return mbedtls_mpi_shift_l( X, 1 );
894
895 T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000896 }
897
898 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200899 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200900
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000901 /*
902 * X should always be positive as a result of unsigned additions.
903 */
904 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000905
Paul Bakker23986e52011-04-24 08:57:21 +0000906 for( j = B->n; j > 0; j-- )
907 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000908 break;
909
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200910 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000911
912 o = B->p; p = X->p; c = 0;
913
Paul Bakker23986e52011-04-24 08:57:21 +0000914 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000915 {
916 *p += c; c = ( *p < c );
917 *p += *o; c += ( *p < *o );
918 }
919
920 while( c != 0 )
921 {
922 if( i >= X->n )
923 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200924 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000925 p = X->p + i;
926 }
927
Paul Bakker2d319fd2012-09-16 21:34:26 +0000928 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000929 }
930
931cleanup:
932
933 return( ret );
934}
935
936/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200937 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000938 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200939static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000940{
Paul Bakker23986e52011-04-24 08:57:21 +0000941 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200942 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000943
944 for( i = c = 0; i < n; i++, s++, d++ )
945 {
946 z = ( *d < c ); *d -= c;
947 c = ( *d < *s ) + z; *d -= *s;
948 }
949
950 while( c != 0 )
951 {
952 z = ( *d < c ); *d -= c;
953 c = z; i++; d++;
954 }
955}
956
957/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100958 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000959 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200960int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000961{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200962 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000963 int ret;
964 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000965
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200966 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
967 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000968
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200969 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000970
971 if( X == B )
972 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200973 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000974 B = &TB;
975 }
976
977 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200978 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000979
Paul Bakker1ef7a532009-06-20 10:50:55 +0000980 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100981 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000982 */
983 X->s = 1;
984
Paul Bakker5121ce52009-01-03 21:22:43 +0000985 ret = 0;
986
Paul Bakker23986e52011-04-24 08:57:21 +0000987 for( n = B->n; n > 0; n-- )
988 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000989 break;
990
Paul Bakker23986e52011-04-24 08:57:21 +0000991 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000992
993cleanup:
994
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200995 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000996
997 return( ret );
998}
999
1000/*
1001 * Signed addition: X = A + B
1002 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001003int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001004{
1005 int ret, s = A->s;
1006
1007 if( A->s * B->s < 0 )
1008 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001009 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001010 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001011 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001012 X->s = s;
1013 }
1014 else
1015 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001017 X->s = -s;
1018 }
1019 }
1020 else
1021 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001022 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001023 X->s = s;
1024 }
1025
1026cleanup:
1027
1028 return( ret );
1029}
1030
1031/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001032 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001033 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001034int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001035{
1036 int ret, s = A->s;
1037
1038 if( A->s * B->s > 0 )
1039 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001040 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001041 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001043 X->s = s;
1044 }
1045 else
1046 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001047 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001048 X->s = -s;
1049 }
1050 }
1051 else
1052 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001053 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001054 X->s = s;
1055 }
1056
1057cleanup:
1058
1059 return( ret );
1060}
1061
1062/*
1063 * Signed addition: X = A + b
1064 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001065int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001066{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001067 mbedtls_mpi _B;
1068 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001069
1070 p[0] = ( b < 0 ) ? -b : b;
1071 _B.s = ( b < 0 ) ? -1 : 1;
1072 _B.n = 1;
1073 _B.p = p;
1074
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001075 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001076}
1077
1078/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001079 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001080 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001081int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001082{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001083 mbedtls_mpi _B;
1084 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001085
1086 p[0] = ( b < 0 ) ? -b : b;
1087 _B.s = ( b < 0 ) ? -1 : 1;
1088 _B.n = 1;
1089 _B.p = p;
1090
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001091 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001092}
1093
1094/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001095 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001096 */
1097static
1098#if defined(__APPLE__) && defined(__arm__)
1099/*
1100 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1101 * appears to need this to prevent bad ARM code generation at -O3.
1102 */
1103__attribute__ ((noinline))
1104#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001105void 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 +00001106{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001107 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001108
1109#if defined(MULADDC_HUIT)
1110 for( ; i >= 8; i -= 8 )
1111 {
1112 MULADDC_INIT
1113 MULADDC_HUIT
1114 MULADDC_STOP
1115 }
1116
1117 for( ; i > 0; i-- )
1118 {
1119 MULADDC_INIT
1120 MULADDC_CORE
1121 MULADDC_STOP
1122 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001123#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001124 for( ; i >= 16; i -= 16 )
1125 {
1126 MULADDC_INIT
1127 MULADDC_CORE MULADDC_CORE
1128 MULADDC_CORE MULADDC_CORE
1129 MULADDC_CORE MULADDC_CORE
1130 MULADDC_CORE MULADDC_CORE
1131
1132 MULADDC_CORE MULADDC_CORE
1133 MULADDC_CORE MULADDC_CORE
1134 MULADDC_CORE MULADDC_CORE
1135 MULADDC_CORE MULADDC_CORE
1136 MULADDC_STOP
1137 }
1138
1139 for( ; i >= 8; i -= 8 )
1140 {
1141 MULADDC_INIT
1142 MULADDC_CORE MULADDC_CORE
1143 MULADDC_CORE MULADDC_CORE
1144
1145 MULADDC_CORE MULADDC_CORE
1146 MULADDC_CORE MULADDC_CORE
1147 MULADDC_STOP
1148 }
1149
1150 for( ; i > 0; i-- )
1151 {
1152 MULADDC_INIT
1153 MULADDC_CORE
1154 MULADDC_STOP
1155 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001156#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001157
1158 t++;
1159
1160 do {
1161 *d += c; c = ( *d < c ); d++;
1162 }
1163 while( c != 0 );
1164}
1165
1166/*
1167 * Baseline multiplication: X = A * B (HAC 14.12)
1168 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001169int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001170{
Paul Bakker23986e52011-04-24 08:57:21 +00001171 int ret;
1172 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001173 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001174
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001175 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001177 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1178 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001179
Paul Bakker23986e52011-04-24 08:57:21 +00001180 for( i = A->n; i > 0; i-- )
1181 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001182 break;
1183
Paul Bakker23986e52011-04-24 08:57:21 +00001184 for( j = B->n; j > 0; j-- )
1185 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001186 break;
1187
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001188 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1189 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001190
Paul Bakker23986e52011-04-24 08:57:21 +00001191 for( i++; j > 0; j-- )
1192 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001193
1194 X->s = A->s * B->s;
1195
1196cleanup:
1197
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001198 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001199
1200 return( ret );
1201}
1202
1203/*
1204 * Baseline multiplication: X = A * b
1205 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001206int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001207{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001208 mbedtls_mpi _B;
1209 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001210
1211 _B.s = 1;
1212 _B.n = 1;
1213 _B.p = p;
1214 p[0] = b;
1215
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001216 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001217}
1218
1219/*
Simon Butcher7ebe2782015-12-28 00:05:30 +00001220 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1221 * mbedtls_mpi_uint divisor, d
Simon Butcherea303e32015-11-26 23:43:34 +00001222 */
Simon Butcher7ebe2782015-12-28 00:05:30 +00001223static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1224 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcherea303e32015-11-26 23:43:34 +00001225{
Manuel Pégourié-Gonnard5a8396e2015-12-01 10:27:00 +01001226#if defined(MBEDTLS_HAVE_UDBL)
1227 mbedtls_t_udbl dividend, quotient;
Simon Butcher7ebe2782015-12-28 00:05:30 +00001228#else
Simon Butcher61891752016-01-03 00:24:34 +00001229 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1230 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcher7ebe2782015-12-28 00:05:30 +00001231 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1232 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher61891752016-01-03 00:24:34 +00001233 size_t s;
Manuel Pégourié-Gonnard5a8396e2015-12-01 10:27:00 +01001234#endif
1235
Simon Butcherea303e32015-11-26 23:43:34 +00001236 /*
1237 * Check for overflow
1238 */
Simon Butcher7ebe2782015-12-28 00:05:30 +00001239 if( 0 == d || u1 >= d )
Simon Butcherea303e32015-11-26 23:43:34 +00001240 {
Simon Butcher7ebe2782015-12-28 00:05:30 +00001241 if (r != NULL) *r = ~0;
Simon Butcherea303e32015-11-26 23:43:34 +00001242
Simon Butcher7ebe2782015-12-28 00:05:30 +00001243 return ( ~0 );
Simon Butcherea303e32015-11-26 23:43:34 +00001244 }
1245
1246#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcherea303e32015-11-26 23:43:34 +00001247 dividend = (mbedtls_t_udbl) u1 << biL;
1248 dividend |= (mbedtls_t_udbl) u0;
1249 quotient = dividend / d;
1250 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1251 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1252
1253 if( r != NULL )
Simon Butcher61891752016-01-03 00:24:34 +00001254 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcherea303e32015-11-26 23:43:34 +00001255
1256 return (mbedtls_mpi_uint) quotient;
1257#else
Simon Butcherea303e32015-11-26 23:43:34 +00001258
1259 /*
1260 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1261 * Vol. 2 - Seminumerical Algorithms, Knuth
1262 */
1263
1264 /*
1265 * Normalize the divisor, d, and dividend, u0, u1
1266 */
1267 s = mbedtls_clz( d );
1268 d = d << s;
1269
1270 u1 = u1 << s;
Simon Butcher61891752016-01-03 00:24:34 +00001271 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcherea303e32015-11-26 23:43:34 +00001272 u0 = u0 << s;
1273
1274 d1 = d >> biH;
Simon Butcher61891752016-01-03 00:24:34 +00001275 d0 = d & uint_halfword_mask;
Simon Butcherea303e32015-11-26 23:43:34 +00001276
1277 u0_msw = u0 >> biH;
Simon Butcher61891752016-01-03 00:24:34 +00001278 u0_lsw = u0 & uint_halfword_mask;
Simon Butcherea303e32015-11-26 23:43:34 +00001279
1280 /*
1281 * Find the first quotient and remainder
1282 */
1283 q1 = u1 / d1;
1284 r0 = u1 - d1 * q1;
1285
1286 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1287 {
1288 q1 -= 1;
1289 r0 += d1;
1290
1291 if ( r0 >= radix ) break;
1292 }
1293
Simon Butcher7ebe2782015-12-28 00:05:30 +00001294 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcherea303e32015-11-26 23:43:34 +00001295 q0 = rAX / d1;
1296 r0 = rAX - q0 * d1;
1297
1298 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1299 {
1300 q0 -= 1;
1301 r0 += d1;
1302
1303 if ( r0 >= radix ) break;
1304 }
1305
1306 if (r != NULL)
Simon Butcher7ebe2782015-12-28 00:05:30 +00001307 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcherea303e32015-11-26 23:43:34 +00001308
1309 quotient = q1 * radix + q0;
1310
1311 return quotient;
1312#endif
1313}
1314
1315/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001316 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001317 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001318int 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 +00001319{
Paul Bakker23986e52011-04-24 08:57:21 +00001320 int ret;
1321 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001322 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001324 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1325 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001327 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1328 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001329
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001330 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001331 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1333 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001334 return( 0 );
1335 }
1336
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001337 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1338 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001339 X.s = Y.s = 1;
1340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001341 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1342 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1343 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1344 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001345
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001346 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001347 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001348 {
1349 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001350 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1351 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001352 }
1353 else k = 0;
1354
1355 n = X.n - 1;
1356 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001357 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001358
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001359 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001360 {
1361 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001362 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001363 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001364 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001365
1366 for( i = n; i > t ; i-- )
1367 {
1368 if( X.p[i] >= Y.p[t] )
1369 Z.p[i - t - 1] = ~0;
1370 else
1371 {
Simon Butcherea303e32015-11-26 23:43:34 +00001372 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1373 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001374 }
1375
1376 Z.p[i - t - 1]++;
1377 do
1378 {
1379 Z.p[i - t - 1]--;
1380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001381 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001382 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001383 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001384 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001385
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001386 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001387 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1388 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001389 T2.p[2] = X.p[i];
1390 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001393 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1394 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1395 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001397 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001398 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1400 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1401 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001402 Z.p[i - t - 1]--;
1403 }
1404 }
1405
1406 if( Q != NULL )
1407 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001408 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001409 Q->s = A->s * B->s;
1410 }
1411
1412 if( R != NULL )
1413 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001415 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001416 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001417
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001418 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001419 R->s = 1;
1420 }
1421
1422cleanup:
1423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001424 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1425 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001426
1427 return( ret );
1428}
1429
1430/*
1431 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001432 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001433int 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 +00001434{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001435 mbedtls_mpi _B;
1436 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001437
1438 p[0] = ( b < 0 ) ? -b : b;
1439 _B.s = ( b < 0 ) ? -1 : 1;
1440 _B.n = 1;
1441 _B.p = p;
1442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001443 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001444}
1445
1446/*
1447 * Modulo: R = A mod B
1448 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001449int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001450{
1451 int ret;
1452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001453 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1454 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001456 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001457
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001458 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1459 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001461 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1462 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001463
1464cleanup:
1465
1466 return( ret );
1467}
1468
1469/*
1470 * Modulo: r = A mod b
1471 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001472int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001473{
Paul Bakker23986e52011-04-24 08:57:21 +00001474 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001475 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001476
1477 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001478 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001479
1480 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001481 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001482
1483 /*
1484 * handle trivial cases
1485 */
1486 if( b == 1 )
1487 {
1488 *r = 0;
1489 return( 0 );
1490 }
1491
1492 if( b == 2 )
1493 {
1494 *r = A->p[0] & 1;
1495 return( 0 );
1496 }
1497
1498 /*
1499 * general case
1500 */
Paul Bakker23986e52011-04-24 08:57:21 +00001501 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001502 {
Paul Bakker23986e52011-04-24 08:57:21 +00001503 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001504 y = ( y << biH ) | ( x >> biH );
1505 z = y / b;
1506 y -= z * b;
1507
1508 x <<= biH;
1509 y = ( y << biH ) | ( x >> biH );
1510 z = y / b;
1511 y -= z * b;
1512 }
1513
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001514 /*
1515 * If A is negative, then the current y represents a negative value.
1516 * Flipping it to the positive side.
1517 */
1518 if( A->s < 0 && y != 0 )
1519 y = b - y;
1520
Paul Bakker5121ce52009-01-03 21:22:43 +00001521 *r = y;
1522
1523 return( 0 );
1524}
1525
1526/*
1527 * Fast Montgomery initialization (thanks to Tom St Denis)
1528 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001529static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001530{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001531 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001532 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001533
1534 x = m0;
1535 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001536
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001537 for( i = biL; i >= 8; i /= 2 )
1538 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001539
1540 *mm = ~x + 1;
1541}
1542
1543/*
1544 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1545 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001546static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1547 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001548{
Paul Bakker23986e52011-04-24 08:57:21 +00001549 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001550 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001551
1552 memset( T->p, 0, T->n * ciL );
1553
1554 d = T->p;
1555 n = N->n;
1556 m = ( B->n < n ) ? B->n : n;
1557
1558 for( i = 0; i < n; i++ )
1559 {
1560 /*
1561 * T = (T + u0*B + u1*N) / 2^biL
1562 */
1563 u0 = A->p[i];
1564 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1565
1566 mpi_mul_hlp( m, B->p, d, u0 );
1567 mpi_mul_hlp( n, N->p, d, u1 );
1568
1569 *d++ = u0; d[n + 1] = 0;
1570 }
1571
Paul Bakker66d5d072014-06-17 16:39:18 +02001572 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001573
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001574 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001575 mpi_sub_hlp( n, N->p, A->p );
1576 else
1577 /* prevent timing attacks */
1578 mpi_sub_hlp( n, A->p, T->p );
1579}
1580
1581/*
1582 * Montgomery reduction: A = A * R^-1 mod N
1583 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001584static 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 +00001585{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001586 mbedtls_mpi_uint z = 1;
1587 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001588
Paul Bakker8ddb6452013-02-27 14:56:33 +01001589 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001590 U.p = &z;
1591
1592 mpi_montmul( A, &U, N, mm, T );
1593}
1594
1595/*
1596 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1597 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001598int 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 +00001599{
Paul Bakker23986e52011-04-24 08:57:21 +00001600 int ret;
1601 size_t wbits, wsize, one = 1;
1602 size_t i, j, nblimbs;
1603 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001604 mbedtls_mpi_uint ei, mm, state;
1605 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001606 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001607
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001608 if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
1609 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001610
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001611 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1612 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001613
1614 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001615 * Init temps and window size
1616 */
1617 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001618 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1619 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001620 memset( W, 0, sizeof( W ) );
1621
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001622 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001623
1624 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1625 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001627 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1628 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001629
Paul Bakker5121ce52009-01-03 21:22:43 +00001630 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001631 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1632 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1633 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001634
1635 /*
Paul Bakker50546922012-05-19 08:40:49 +00001636 * Compensate for negative A (and correct at the end)
1637 */
1638 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001639 if( neg )
1640 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001641 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001642 Apos.s = 1;
1643 A = &Apos;
1644 }
1645
1646 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001647 * If 1st call, pre-compute R^2 mod N
1648 */
1649 if( _RR == NULL || _RR->p == NULL )
1650 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1652 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1653 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001654
1655 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001656 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001657 }
1658 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001659 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001660
1661 /*
1662 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1663 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001664 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1665 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001666 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001667 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001668
1669 mpi_montmul( &W[1], &RR, N, mm, &T );
1670
1671 /*
1672 * X = R^2 * R^-1 mod N = R mod N
1673 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001674 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001675 mpi_montred( X, N, mm, &T );
1676
1677 if( wsize > 1 )
1678 {
1679 /*
1680 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1681 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001682 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001684 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1685 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001686
1687 for( i = 0; i < wsize - 1; i++ )
1688 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001689
Paul Bakker5121ce52009-01-03 21:22:43 +00001690 /*
1691 * W[i] = W[i - 1] * W[1]
1692 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001693 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001694 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001695 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1696 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001697
1698 mpi_montmul( &W[i], &W[1], N, mm, &T );
1699 }
1700 }
1701
1702 nblimbs = E->n;
1703 bufsize = 0;
1704 nbits = 0;
1705 wbits = 0;
1706 state = 0;
1707
1708 while( 1 )
1709 {
1710 if( bufsize == 0 )
1711 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001712 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001713 break;
1714
Paul Bakker0d7702c2013-10-29 16:18:35 +01001715 nblimbs--;
1716
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001717 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001718 }
1719
1720 bufsize--;
1721
1722 ei = (E->p[nblimbs] >> bufsize) & 1;
1723
1724 /*
1725 * skip leading 0s
1726 */
1727 if( ei == 0 && state == 0 )
1728 continue;
1729
1730 if( ei == 0 && state == 1 )
1731 {
1732 /*
1733 * out of window, square X
1734 */
1735 mpi_montmul( X, X, N, mm, &T );
1736 continue;
1737 }
1738
1739 /*
1740 * add ei to current window
1741 */
1742 state = 2;
1743
1744 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001745 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001746
1747 if( nbits == wsize )
1748 {
1749 /*
1750 * X = X^wsize R^-1 mod N
1751 */
1752 for( i = 0; i < wsize; i++ )
1753 mpi_montmul( X, X, N, mm, &T );
1754
1755 /*
1756 * X = X * W[wbits] R^-1 mod N
1757 */
1758 mpi_montmul( X, &W[wbits], N, mm, &T );
1759
1760 state--;
1761 nbits = 0;
1762 wbits = 0;
1763 }
1764 }
1765
1766 /*
1767 * process the remaining bits
1768 */
1769 for( i = 0; i < nbits; i++ )
1770 {
1771 mpi_montmul( X, X, N, mm, &T );
1772
1773 wbits <<= 1;
1774
Paul Bakker66d5d072014-06-17 16:39:18 +02001775 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001776 mpi_montmul( X, &W[1], N, mm, &T );
1777 }
1778
1779 /*
1780 * X = A^E * R * R^-1 mod N = A^E mod N
1781 */
1782 mpi_montred( X, N, mm, &T );
1783
Paul Bakkerf6198c12012-05-16 08:02:29 +00001784 if( neg )
1785 {
1786 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001787 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001788 }
1789
Paul Bakker5121ce52009-01-03 21:22:43 +00001790cleanup:
1791
Paul Bakker66d5d072014-06-17 16:39:18 +02001792 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001793 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001794
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001795 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001796
Paul Bakker75a28602014-03-31 12:08:17 +02001797 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001798 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001799
1800 return( ret );
1801}
1802
Paul Bakker5121ce52009-01-03 21:22:43 +00001803/*
1804 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1805 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001806int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001807{
Paul Bakker23986e52011-04-24 08:57:21 +00001808 int ret;
1809 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001810 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001811
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001812 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001813
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001814 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1815 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001816
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001817 lz = mbedtls_mpi_lsb( &TA );
1818 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001819
Paul Bakker66d5d072014-06-17 16:39:18 +02001820 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001821 lz = lzt;
1822
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001823 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1824 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001825
Paul Bakker5121ce52009-01-03 21:22:43 +00001826 TA.s = TB.s = 1;
1827
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001828 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001829 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1831 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001832
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001833 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001834 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001835 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1836 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001837 }
1838 else
1839 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001840 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1841 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001842 }
1843 }
1844
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001845 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1846 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001847
1848cleanup:
1849
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001850 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001851
1852 return( ret );
1853}
1854
Paul Bakker33dc46b2014-04-30 16:11:39 +02001855/*
1856 * Fill X with size bytes of random.
1857 *
1858 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001859 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001860 * deterministic, eg for tests).
1861 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001862int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001863 int (*f_rng)(void *, unsigned char *, size_t),
1864 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001865{
Paul Bakker23986e52011-04-24 08:57:21 +00001866 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001867 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001868
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001869 if( size > MBEDTLS_MPI_MAX_SIZE )
1870 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001871
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001872 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1873 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001874
1875cleanup:
1876 return( ret );
1877}
1878
Paul Bakker5121ce52009-01-03 21:22:43 +00001879/*
1880 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1881 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001883{
1884 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001885 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001886
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001887 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 )
1888 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001889
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001890 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1891 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1892 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001893
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001895
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001896 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001897 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001898 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001899 goto cleanup;
1900 }
1901
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001902 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1903 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1904 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1905 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001906
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001907 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1908 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1909 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1910 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001911
1912 do
1913 {
1914 while( ( TU.p[0] & 1 ) == 0 )
1915 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001916 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001917
1918 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1919 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001920 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1921 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001922 }
1923
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001924 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1925 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001926 }
1927
1928 while( ( TV.p[0] & 1 ) == 0 )
1929 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001930 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001931
1932 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1933 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001934 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1935 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001936 }
1937
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001938 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1939 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001940 }
1941
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001942 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001943 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001944 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1945 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1946 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001947 }
1948 else
1949 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001950 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1951 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1952 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001953 }
1954 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001955 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001957 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1958 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001959
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001960 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1961 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001962
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001964
1965cleanup:
1966
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001967 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1968 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1969 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001970
1971 return( ret );
1972}
1973
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001974#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001975
Paul Bakker5121ce52009-01-03 21:22:43 +00001976static const int small_prime[] =
1977{
1978 3, 5, 7, 11, 13, 17, 19, 23,
1979 29, 31, 37, 41, 43, 47, 53, 59,
1980 61, 67, 71, 73, 79, 83, 89, 97,
1981 101, 103, 107, 109, 113, 127, 131, 137,
1982 139, 149, 151, 157, 163, 167, 173, 179,
1983 181, 191, 193, 197, 199, 211, 223, 227,
1984 229, 233, 239, 241, 251, 257, 263, 269,
1985 271, 277, 281, 283, 293, 307, 311, 313,
1986 317, 331, 337, 347, 349, 353, 359, 367,
1987 373, 379, 383, 389, 397, 401, 409, 419,
1988 421, 431, 433, 439, 443, 449, 457, 461,
1989 463, 467, 479, 487, 491, 499, 503, 509,
1990 521, 523, 541, 547, 557, 563, 569, 571,
1991 577, 587, 593, 599, 601, 607, 613, 617,
1992 619, 631, 641, 643, 647, 653, 659, 661,
1993 673, 677, 683, 691, 701, 709, 719, 727,
1994 733, 739, 743, 751, 757, 761, 769, 773,
1995 787, 797, 809, 811, 821, 823, 827, 829,
1996 839, 853, 857, 859, 863, 877, 881, 883,
1997 887, 907, 911, 919, 929, 937, 941, 947,
1998 953, 967, 971, 977, 983, 991, 997, -103
1999};
2000
2001/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002002 * Small divisors test (X must be positive)
2003 *
2004 * Return values:
2005 * 0: no small factor (possible prime, more tests needed)
2006 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002007 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002008 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002009 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002010static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002011{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002012 int ret = 0;
2013 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002014 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002015
Paul Bakker5121ce52009-01-03 21:22:43 +00002016 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002017 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002018
2019 for( i = 0; small_prime[i] > 0; i++ )
2020 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002021 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002022 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002023
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002024 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002025
2026 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002027 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002028 }
2029
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002030cleanup:
2031 return( ret );
2032}
2033
2034/*
2035 * Miller-Rabin pseudo-primality test (HAC 4.24)
2036 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002037static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002038 int (*f_rng)(void *, unsigned char *, size_t),
2039 void *p_rng )
2040{
Pascal Junodb99183d2015-03-11 16:49:45 +01002041 int ret, count;
2042 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002043 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002044
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002045 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2046 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002047
Paul Bakker5121ce52009-01-03 21:22:43 +00002048 /*
2049 * W = |X| - 1
2050 * R = W >> lsb( W )
2051 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2053 s = mbedtls_mpi_lsb( &W );
2054 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2055 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002056
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002057 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002058 /*
2059 * HAC, table 4.4
2060 */
2061 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2062 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2063 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2064
2065 for( i = 0; i < n; i++ )
2066 {
2067 /*
2068 * pick a random A, 1 < A < |X| - 1
2069 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002070 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002071
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002072 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00002073 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002074 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002075 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00002076 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002077 A.p[0] |= 3;
2078
Pascal Junodb99183d2015-03-11 16:49:45 +01002079 count = 0;
2080 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002081 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002082
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002083 j = mbedtls_mpi_bitlen( &A );
2084 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002085 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002086 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002087 }
2088
2089 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002090 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002091 }
2092
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002093 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2094 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002095
2096 /*
2097 * A = A^R mod |X|
2098 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002099 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002100
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002101 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2102 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002103 continue;
2104
2105 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002106 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002107 {
2108 /*
2109 * A = A * A mod |X|
2110 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002111 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2112 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002113
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002114 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002115 break;
2116
2117 j++;
2118 }
2119
2120 /*
2121 * not prime if A != |X| - 1 or A == 1
2122 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002123 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2124 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002125 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002126 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002127 break;
2128 }
2129 }
2130
2131cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002132 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2133 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002134
2135 return( ret );
2136}
2137
2138/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002139 * Pseudo-primality test: small factors, then Miller-Rabin
2140 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002141int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002142 int (*f_rng)(void *, unsigned char *, size_t),
2143 void *p_rng )
2144{
2145 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002146 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002147
2148 XX.s = 1;
2149 XX.n = X->n;
2150 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002152 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2153 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2154 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002155
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002156 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002157 return( 0 );
2158
2159 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2160 {
2161 if( ret == 1 )
2162 return( 0 );
2163
2164 return( ret );
2165 }
2166
2167 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2168}
2169
2170/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002171 * Prime number generation
2172 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002173int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002174 int (*f_rng)(void *, unsigned char *, size_t),
2175 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002176{
Paul Bakker23986e52011-04-24 08:57:21 +00002177 int ret;
2178 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002179 mbedtls_mpi_uint r;
2180 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002182 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2183 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002185 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002186
2187 n = BITS_TO_LIMBS( nbits );
2188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002189 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002190
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002191 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002192 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002193
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002194 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002195
2196 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002197
2198 if( dh_flag == 0 )
2199 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002200 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002201 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002202 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002203 goto cleanup;
2204
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002205 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002206 }
2207 }
2208 else
2209 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002210 /*
2211 * An necessary condition for Y and X = 2Y + 1 to be prime
2212 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2213 * Make sure it is satisfied, while keeping X = 3 mod 4
2214 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002215
2216 X->p[0] |= 2;
2217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002218 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002219 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002220 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002221 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002222 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002223
2224 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002225 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2226 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002227
2228 while( 1 )
2229 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002230 /*
2231 * First, check small factors for X and Y
2232 * before doing Miller-Rabin on any of them
2233 */
2234 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2235 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2236 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2237 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002238 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002239 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002240 }
2241
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002242 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002243 goto cleanup;
2244
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002245 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002246 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002247 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2248 * so up Y by 6 and X by 12.
2249 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002250 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2251 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002252 }
2253 }
2254
2255cleanup:
2256
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002257 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002258
2259 return( ret );
2260}
2261
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002262#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002265
Paul Bakker23986e52011-04-24 08:57:21 +00002266#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002267
2268static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2269{
2270 { 693, 609, 21 },
2271 { 1764, 868, 28 },
2272 { 768454923, 542167814, 1 }
2273};
2274
Paul Bakker5121ce52009-01-03 21:22:43 +00002275/*
2276 * Checkup routine
2277 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002278int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002279{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002280 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002281 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002283 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2284 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002285
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002286 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002287 "EFE021C2645FD1DC586E69184AF4A31E" \
2288 "D5F53E93B5F123FA41680867BA110131" \
2289 "944FE7952E2517337780CB0DB80E61AA" \
2290 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2291
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002292 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002293 "B2E7EFD37075B9F03FF989C7C5051C20" \
2294 "34D2A323810251127E7BF8625A4F49A5" \
2295 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2296 "5B5C25763222FEFCCFC38B832366C29E" ) );
2297
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002298 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002299 "0066A198186C18C10B2F5ED9B522752A" \
2300 "9830B69916E535C8F047518A889A43A5" \
2301 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2302
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002303 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002304
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002305 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002306 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2307 "9E857EA95A03512E2BAE7391688D264A" \
2308 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2309 "8001B72E848A38CAE1C65F78E56ABDEF" \
2310 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2311 "ECF677152EF804370C1A305CAF3B5BF1" \
2312 "30879B56C61DE584A0F53A2447A51E" ) );
2313
2314 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002315 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002316
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002317 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002318 {
2319 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002320 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002321
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002322 ret = 1;
2323 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002324 }
2325
2326 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002327 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002329 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002330
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002331 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002332 "256567336059E52CAE22925474705F39A94" ) );
2333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002334 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002335 "6613F26162223DF488E9CD48CC132C7A" \
2336 "0AC93C701B001B092E4E5B9F73BCD27B" \
2337 "9EE50D0657C77F374E903CDFA4C642" ) );
2338
2339 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002340 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2343 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002344 {
2345 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002346 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002347
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002348 ret = 1;
2349 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002350 }
2351
2352 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002354
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002355 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002356
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002357 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002358 "36E139AEA55215609D2816998ED020BB" \
2359 "BD96C37890F65171D948E9BC7CBAA4D9" \
2360 "325D24D6A3C12710F10A09FA08AB87" ) );
2361
2362 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002363 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002364
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002365 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002366 {
2367 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002368 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002369
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002370 ret = 1;
2371 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002372 }
2373
2374 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002375 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002376
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002377 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002379 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002380 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2381 "C3DBA76456363A10869622EAC2DD84EC" \
2382 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2383
2384 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002386
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002387 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002388 {
2389 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002390 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002391
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002392 ret = 1;
2393 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002394 }
2395
2396 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002397 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002398
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002399 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002400 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002401
Paul Bakker66d5d072014-06-17 16:39:18 +02002402 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002403 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002404 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2405 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002406
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002407 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002409 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002410 {
2411 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002412 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002413
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002414 ret = 1;
2415 goto cleanup;
2416 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002417 }
2418
2419 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002420 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002421
Paul Bakker5121ce52009-01-03 21:22:43 +00002422cleanup:
2423
2424 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002425 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002426
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002427 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2428 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002429
2430 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002431 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002432
2433 return( ret );
2434}
2435
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002436#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002437
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002438#endif /* MBEDTLS_BIGNUM_C */