blob: 61aa961c6e6141285fb7a84b896ee86553a8928a [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcherea303e32015-11-26 23:43:34 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcherea303e32015-11-26 23:43:34 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcherea303e32015-11-26 23:43:34 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcher7ebe2782015-12-28 00:05:30 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000048
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <string.h>
50
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000052#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020053#else
Rich Evans00ab4702015-02-06 13:43:58 +000054#include <stdio.h>
55#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020057#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020059#endif
60
Paul Bakker34617722014-06-13 17:20:13 +020061/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020062static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020063 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
64}
65
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020066#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000067#define biL (ciL << 3) /* bits in limb */
68#define biH (ciL << 2) /* half limb size */
69
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010070#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
71
Paul Bakker5121ce52009-01-03 21:22:43 +000072/*
73 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020074 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000075 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020076#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
77#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000078
79/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000080 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000081 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000083{
Paul Bakker6c591fa2011-05-05 11:49:20 +000084 if( X == NULL )
85 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000086
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 X->s = 1;
88 X->n = 0;
89 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000090}
91
92/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000094 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020095void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000096{
Paul Bakker6c591fa2011-05-05 11:49:20 +000097 if( X == NULL )
98 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000099
Paul Bakker6c591fa2011-05-05 11:49:20 +0000100 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000101 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200102 mbedtls_zeroize( X->p, X->n * ciL );
103 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000104 }
105
Paul Bakker6c591fa2011-05-05 11:49:20 +0000106 X->s = 1;
107 X->n = 0;
108 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000109}
110
111/*
112 * Enlarge to the specified number of limbs
113 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200114int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000115{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000117
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200118 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200119 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000120
Paul Bakker5121ce52009-01-03 21:22:43 +0000121 if( X->n < nblimbs )
122 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200123 if( ( p = mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200124 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000125
Paul Bakker5121ce52009-01-03 21:22:43 +0000126 if( X->p != NULL )
127 {
128 memcpy( p, X->p, X->n * ciL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 mbedtls_zeroize( X->p, X->n * ciL );
130 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000131 }
132
133 X->n = nblimbs;
134 X->p = p;
135 }
136
137 return( 0 );
138}
139
140/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100141 * Resize down as much as possible,
142 * while keeping at least the specified number of limbs
143 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100145{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100147 size_t i;
148
149 /* Actually resize up in this case */
150 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152
153 for( i = X->n - 1; i > 0; i-- )
154 if( X->p[i] != 0 )
155 break;
156 i++;
157
158 if( i < nblimbs )
159 i = nblimbs;
160
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200161 if( ( p = mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200162 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100164 if( X->p != NULL )
165 {
166 memcpy( p, X->p, i * ciL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200167 mbedtls_zeroize( X->p, X->n * ciL );
168 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100169 }
170
171 X->n = i;
172 X->p = p;
173
174 return( 0 );
175}
176
177/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000178 * Copy the contents of Y into X
179 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000181{
Paul Bakker23986e52011-04-24 08:57:21 +0000182 int ret;
183 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000184
185 if( X == Y )
186 return( 0 );
187
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200188 if( Y->p == NULL )
189 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200191 return( 0 );
192 }
193
Paul Bakker5121ce52009-01-03 21:22:43 +0000194 for( i = Y->n - 1; i > 0; i-- )
195 if( Y->p[i] != 0 )
196 break;
197 i++;
198
199 X->s = Y->s;
200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200201 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000202
203 memset( X->p, 0, X->n * ciL );
204 memcpy( X->p, Y->p, i * ciL );
205
206cleanup:
207
208 return( ret );
209}
210
211/*
212 * Swap the contents of X and Y
213 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200214void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000215{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218 memcpy( &T, X, sizeof( mbedtls_mpi ) );
219 memcpy( X, Y, sizeof( mbedtls_mpi ) );
220 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000221}
222
223/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100224 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100225 * about whether the assignment was made or not.
226 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100227 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100229{
230 int ret = 0;
231 size_t i;
232
Pascal Junodb99183d2015-03-11 16:49:45 +0100233 /* make sure assign is 0 or 1 in a time-constant manner */
234 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100235
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100237
Paul Bakker66d5d072014-06-17 16:39:18 +0200238 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100239
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100240 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200241 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100242
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100243 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200244 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100245
246cleanup:
247 return( ret );
248}
249
250/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100251 * Conditionally swap X and Y, without leaking information
252 * about whether the swap was made or not.
253 * Here it is not ok to simply swap the pointers, which whould lead to
254 * different memory access patterns when X and Y are used afterwards.
255 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100257{
258 int ret, s;
259 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100261
262 if( X == Y )
263 return( 0 );
264
Pascal Junodb99183d2015-03-11 16:49:45 +0100265 /* make sure swap is 0 or 1 in a time-constant manner */
266 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
269 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100270
271 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200272 X->s = X->s * ( 1 - swap ) + Y->s * swap;
273 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274
275
276 for( i = 0; i < X->n; i++ )
277 {
278 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200279 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
280 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100281 }
282
283cleanup:
284 return( ret );
285}
286
287/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000288 * Set value from integer
289 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200290int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000291{
292 int ret;
293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000295 memset( X->p, 0, X->n * ciL );
296
297 X->p[0] = ( z < 0 ) ? -z : z;
298 X->s = ( z < 0 ) ? -1 : 1;
299
300cleanup:
301
302 return( ret );
303}
304
305/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000306 * Get a specific bit
307 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000309{
310 if( X->n * biL <= pos )
311 return( 0 );
312
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200313 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000314}
315
316/*
317 * Set a bit to a specific value of 0 or 1
318 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200319int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000320{
321 int ret = 0;
322 size_t off = pos / biL;
323 size_t idx = pos % biL;
324
325 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200327
Paul Bakker2f5947e2011-05-18 15:47:11 +0000328 if( X->n * biL <= pos )
329 {
330 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200331 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200333 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000334 }
335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
337 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338
339cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200340
Paul Bakker2f5947e2011-05-18 15:47:11 +0000341 return( ret );
342}
343
344/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200345 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000346 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000348{
Paul Bakker23986e52011-04-24 08:57:21 +0000349 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000350
351 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000352 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000353 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
354 return( count );
355
356 return( 0 );
357}
358
359/*
Simon Butcherea303e32015-11-26 23:43:34 +0000360 * Count leading zero bits in a given integer
361 */
362static size_t mbedtls_clz( const mbedtls_mpi_uint x )
363{
364 size_t j;
Manuel Pégourié-Gonnard3eab29a2015-12-01 09:31:52 +0100365 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcherea303e32015-11-26 23:43:34 +0000366
367 for( j = 0; j < biL; j++ )
368 {
369 if( x & mask ) break;
370
371 mask >>= 1;
372 }
373
374 return j;
375}
376
377/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200378 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200380size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000381{
Paul Bakker23986e52011-04-24 08:57:21 +0000382 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000383
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200384 if( X->n == 0 )
385 return( 0 );
386
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 for( i = X->n - 1; i > 0; i-- )
388 if( X->p[i] != 0 )
389 break;
390
Simon Butcherea303e32015-11-26 23:43:34 +0000391 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000392
Paul Bakker23986e52011-04-24 08:57:21 +0000393 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000394}
395
396/*
397 * Return the total size in bytes
398 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000400{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200401 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000402}
403
404/*
405 * Convert an ASCII character to digit value
406 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000408{
409 *d = 255;
410
411 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
412 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
413 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
414
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415 if( *d >= (mbedtls_mpi_uint) radix )
416 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
418 return( 0 );
419}
420
421/*
422 * Import from an ASCII string
423 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000425{
Paul Bakker23986e52011-04-24 08:57:21 +0000426 int ret;
427 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 mbedtls_mpi_uint d;
429 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000430
431 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000435
Paul Bakkerff60ee62010-03-16 21:09:09 +0000436 slen = strlen( s );
437
Paul Bakker5121ce52009-01-03 21:22:43 +0000438 if( radix == 16 )
439 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100440 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200441 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
442
Paul Bakkerff60ee62010-03-16 21:09:09 +0000443 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
446 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000447
Paul Bakker23986e52011-04-24 08:57:21 +0000448 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000449 {
Paul Bakker23986e52011-04-24 08:57:21 +0000450 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000451 {
452 X->s = -1;
453 break;
454 }
455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200457 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 }
459 }
460 else
461 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000463
Paul Bakkerff60ee62010-03-16 21:09:09 +0000464 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000465 {
466 if( i == 0 && s[i] == '-' )
467 {
468 X->s = -1;
469 continue;
470 }
471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
473 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000474
475 if( X->s == 1 )
476 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000478 }
479 else
480 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000482 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000483 }
484 }
485
486cleanup:
487
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200488 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000489
490 return( ret );
491}
492
493/*
494 * Helper to write the digits high-order first
495 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000497{
498 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000500
501 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
505 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
508 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000509
510 if( r < 10 )
511 *(*p)++ = (char)( r + 0x30 );
512 else
513 *(*p)++ = (char)( r + 0x37 );
514
515cleanup:
516
517 return( ret );
518}
519
520/*
521 * Export into an ASCII string
522 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100523int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
524 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000525{
Paul Bakker23986e52011-04-24 08:57:21 +0000526 int ret = 0;
527 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000528 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000530
531 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000533
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200534 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000535 if( radix >= 4 ) n >>= 1;
536 if( radix >= 16 ) n >>= 1;
Andres AGe0545c32017-01-06 13:17:35 +0000537 /*
538 * Round up the buffer length to an even value to ensure that there is
539 * enough room for hexadecimal values that can be represented in an odd
540 * number of digits.
541 */
542 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000543
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100544 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000545 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100546 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200547 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000548 }
549
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100550 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200551 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000552
553 if( X->s == -1 )
554 *p++ = '-';
555
556 if( radix == 16 )
557 {
Paul Bakker23986e52011-04-24 08:57:21 +0000558 int c;
559 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000560
Paul Bakker23986e52011-04-24 08:57:21 +0000561 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000562 {
Paul Bakker23986e52011-04-24 08:57:21 +0000563 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000564 {
Paul Bakker23986e52011-04-24 08:57:21 +0000565 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000566
Paul Bakker6c343d72014-07-10 14:36:19 +0200567 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000568 continue;
569
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000570 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000571 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000572 k = 1;
573 }
574 }
575 }
576 else
577 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000579
580 if( T.s == -1 )
581 T.s = 1;
582
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200583 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000584 }
585
586 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100587 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000588
589cleanup:
590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000592
593 return( ret );
594}
595
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200596#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000597/*
598 * Read X from an opened file
599 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200600int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000601{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000603 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000604 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000605 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000606 * Buffer should have space for (short) label and decimal formatted MPI,
607 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000608 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200609 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000610
611 memset( s, 0, sizeof( s ) );
612 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000614
615 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000616 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000618
Hanno Becker4195e802017-04-26 11:46:46 +0100619 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
620 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000621
622 p = s + slen;
Hanno Becker4195e802017-04-26 11:46:46 +0100623 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000624 if( mpi_get_digit( &d, radix, *p ) != 0 )
625 break;
626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200627 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000628}
629
630/*
631 * Write X into an opened file (or stdout if fout == NULL)
632 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200633int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000634{
Paul Bakker23986e52011-04-24 08:57:21 +0000635 int ret;
636 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000637 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000638 * Buffer should have space for (short) label and decimal formatted MPI,
639 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000640 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000642
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100643 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000644
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100645 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000646
647 if( p == NULL ) p = "";
648
649 plen = strlen( p );
650 slen = strlen( s );
651 s[slen++] = '\r';
652 s[slen++] = '\n';
653
654 if( fout != NULL )
655 {
656 if( fwrite( p, 1, plen, fout ) != plen ||
657 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000659 }
660 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000662
663cleanup:
664
665 return( ret );
666}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000668
669/*
670 * Import X from unsigned binary data, big endian
671 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000673{
Paul Bakker23986e52011-04-24 08:57:21 +0000674 int ret;
Hanno Becker7d806882017-10-17 15:17:27 +0100675 size_t i, j;
676 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000677
Hanno Becker7d806882017-10-17 15:17:27 +0100678 /* Ensure that target MPI has exactly the necessary number of limbs */
679 if( X->n != limbs )
680 {
681 mbedtls_mpi_free( X );
682 mbedtls_mpi_init( X );
683 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
684 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000685
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200686 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000687
Hanno Becker7d806882017-10-17 15:17:27 +0100688 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000690
691cleanup:
692
693 return( ret );
694}
695
696/*
697 * Export X into unsigned binary data, big endian
698 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200699int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000700{
Paul Bakker23986e52011-04-24 08:57:21 +0000701 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000702
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000704
705 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
708 memset( buf, 0, buflen );
709
710 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
711 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
712
713 return( 0 );
714}
715
716/*
717 * Left-shift: X <<= count
718 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000720{
Paul Bakker23986e52011-04-24 08:57:21 +0000721 int ret;
722 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200723 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000724
725 v0 = count / (biL );
726 t1 = count & (biL - 1);
727
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200728 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000729
Paul Bakkerf9688572011-05-05 10:00:45 +0000730 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000732
733 ret = 0;
734
735 /*
736 * shift by count / limb_size
737 */
738 if( v0 > 0 )
739 {
Paul Bakker23986e52011-04-24 08:57:21 +0000740 for( i = X->n; i > v0; i-- )
741 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000742
Paul Bakker23986e52011-04-24 08:57:21 +0000743 for( ; i > 0; i-- )
744 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000745 }
746
747 /*
748 * shift by count % limb_size
749 */
750 if( t1 > 0 )
751 {
752 for( i = v0; i < X->n; i++ )
753 {
754 r1 = X->p[i] >> (biL - t1);
755 X->p[i] <<= t1;
756 X->p[i] |= r0;
757 r0 = r1;
758 }
759 }
760
761cleanup:
762
763 return( ret );
764}
765
766/*
767 * Right-shift: X >>= count
768 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200769int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000770{
Paul Bakker23986e52011-04-24 08:57:21 +0000771 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200772 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000773
774 v0 = count / biL;
775 v1 = count & (biL - 1);
776
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100777 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200778 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100779
Paul Bakker5121ce52009-01-03 21:22:43 +0000780 /*
781 * shift by count / limb_size
782 */
783 if( v0 > 0 )
784 {
785 for( i = 0; i < X->n - v0; i++ )
786 X->p[i] = X->p[i + v0];
787
788 for( ; i < X->n; i++ )
789 X->p[i] = 0;
790 }
791
792 /*
793 * shift by count % limb_size
794 */
795 if( v1 > 0 )
796 {
Paul Bakker23986e52011-04-24 08:57:21 +0000797 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000798 {
Paul Bakker23986e52011-04-24 08:57:21 +0000799 r1 = X->p[i - 1] << (biL - v1);
800 X->p[i - 1] >>= v1;
801 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000802 r0 = r1;
803 }
804 }
805
806 return( 0 );
807}
808
809/*
810 * Compare unsigned values
811 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200812int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000813{
Paul Bakker23986e52011-04-24 08:57:21 +0000814 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000815
Paul Bakker23986e52011-04-24 08:57:21 +0000816 for( i = X->n; i > 0; i-- )
817 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000818 break;
819
Paul Bakker23986e52011-04-24 08:57:21 +0000820 for( j = Y->n; j > 0; j-- )
821 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000822 break;
823
Paul Bakker23986e52011-04-24 08:57:21 +0000824 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000825 return( 0 );
826
827 if( i > j ) return( 1 );
828 if( j > i ) return( -1 );
829
Paul Bakker23986e52011-04-24 08:57:21 +0000830 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000831 {
Paul Bakker23986e52011-04-24 08:57:21 +0000832 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
833 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000834 }
835
836 return( 0 );
837}
838
839/*
840 * Compare signed values
841 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200842int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000843{
Paul Bakker23986e52011-04-24 08:57:21 +0000844 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000845
Paul Bakker23986e52011-04-24 08:57:21 +0000846 for( i = X->n; i > 0; i-- )
847 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000848 break;
849
Paul Bakker23986e52011-04-24 08:57:21 +0000850 for( j = Y->n; j > 0; j-- )
851 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000852 break;
853
Paul Bakker23986e52011-04-24 08:57:21 +0000854 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000855 return( 0 );
856
857 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000858 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000859
860 if( X->s > 0 && Y->s < 0 ) return( 1 );
861 if( Y->s > 0 && X->s < 0 ) return( -1 );
862
Paul Bakker23986e52011-04-24 08:57:21 +0000863 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000864 {
Paul Bakker23986e52011-04-24 08:57:21 +0000865 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
866 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000867 }
868
869 return( 0 );
870}
871
872/*
873 * Compare signed values
874 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200875int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000876{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200877 mbedtls_mpi Y;
878 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000879
880 *p = ( z < 0 ) ? -z : z;
881 Y.s = ( z < 0 ) ? -1 : 1;
882 Y.n = 1;
883 Y.p = p;
884
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200885 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000886}
887
888/*
889 * Unsigned addition: X = |A| + |B| (HAC 14.7)
890 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200891int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000892{
Paul Bakker23986e52011-04-24 08:57:21 +0000893 int ret;
894 size_t i, j;
Janos Follath79a1da62015-10-30 17:43:11 +0100895 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000896
897 if( X == B )
898 {
Janos Follath79a1da62015-10-30 17:43:11 +0100899 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000900 }
901
902 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200903 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200904
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000905 /*
906 * X should always be positive as a result of unsigned additions.
907 */
908 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000909
Paul Bakker23986e52011-04-24 08:57:21 +0000910 for( j = B->n; j > 0; j-- )
911 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000912 break;
913
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200914 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000915
916 o = B->p; p = X->p; c = 0;
917
Janos Follath79a1da62015-10-30 17:43:11 +0100918 /*
919 * tmp is used because it might happen that p == o
920 */
Paul Bakker23986e52011-04-24 08:57:21 +0000921 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000922 {
Janos Follath79a1da62015-10-30 17:43:11 +0100923 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000924 *p += c; c = ( *p < c );
Janos Follath79a1da62015-10-30 17:43:11 +0100925 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000926 }
927
928 while( c != 0 )
929 {
930 if( i >= X->n )
931 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200932 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000933 p = X->p + i;
934 }
935
Paul Bakker2d319fd2012-09-16 21:34:26 +0000936 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000937 }
938
939cleanup:
940
941 return( ret );
942}
943
944/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200945 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000946 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000948{
Paul Bakker23986e52011-04-24 08:57:21 +0000949 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200950 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000951
952 for( i = c = 0; i < n; i++, s++, d++ )
953 {
954 z = ( *d < c ); *d -= c;
955 c = ( *d < *s ) + z; *d -= *s;
956 }
957
958 while( c != 0 )
959 {
960 z = ( *d < c ); *d -= c;
961 c = z; i++; d++;
962 }
963}
964
965/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100966 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000967 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200968int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000969{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200970 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000971 int ret;
972 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000973
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200974 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
975 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000976
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000978
979 if( X == B )
980 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200981 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000982 B = &TB;
983 }
984
985 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200986 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000987
Paul Bakker1ef7a532009-06-20 10:50:55 +0000988 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100989 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000990 */
991 X->s = 1;
992
Paul Bakker5121ce52009-01-03 21:22:43 +0000993 ret = 0;
994
Paul Bakker23986e52011-04-24 08:57:21 +0000995 for( n = B->n; n > 0; n-- )
996 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000997 break;
998
Paul Bakker23986e52011-04-24 08:57:21 +0000999 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001000
1001cleanup:
1002
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001003 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001004
1005 return( ret );
1006}
1007
1008/*
1009 * Signed addition: X = A + B
1010 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001011int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001012{
1013 int ret, s = A->s;
1014
1015 if( A->s * B->s < 0 )
1016 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001017 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001018 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001020 X->s = s;
1021 }
1022 else
1023 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001024 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001025 X->s = -s;
1026 }
1027 }
1028 else
1029 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001030 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001031 X->s = s;
1032 }
1033
1034cleanup:
1035
1036 return( ret );
1037}
1038
1039/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001040 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001041 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001043{
1044 int ret, s = A->s;
1045
1046 if( A->s * B->s > 0 )
1047 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001048 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001049 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001051 X->s = s;
1052 }
1053 else
1054 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001055 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001056 X->s = -s;
1057 }
1058 }
1059 else
1060 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001061 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001062 X->s = s;
1063 }
1064
1065cleanup:
1066
1067 return( ret );
1068}
1069
1070/*
1071 * Signed addition: X = A + b
1072 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001073int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001074{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001075 mbedtls_mpi _B;
1076 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001077
1078 p[0] = ( b < 0 ) ? -b : b;
1079 _B.s = ( b < 0 ) ? -1 : 1;
1080 _B.n = 1;
1081 _B.p = p;
1082
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001083 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001084}
1085
1086/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001087 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001088 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001089int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001090{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001091 mbedtls_mpi _B;
1092 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001093
1094 p[0] = ( b < 0 ) ? -b : b;
1095 _B.s = ( b < 0 ) ? -1 : 1;
1096 _B.n = 1;
1097 _B.p = p;
1098
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001099 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001100}
1101
1102/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001103 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001104 */
1105static
1106#if defined(__APPLE__) && defined(__arm__)
1107/*
1108 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1109 * appears to need this to prevent bad ARM code generation at -O3.
1110 */
1111__attribute__ ((noinline))
1112#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001113void 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 +00001114{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001116
1117#if defined(MULADDC_HUIT)
1118 for( ; i >= 8; i -= 8 )
1119 {
1120 MULADDC_INIT
1121 MULADDC_HUIT
1122 MULADDC_STOP
1123 }
1124
1125 for( ; i > 0; i-- )
1126 {
1127 MULADDC_INIT
1128 MULADDC_CORE
1129 MULADDC_STOP
1130 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001131#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001132 for( ; i >= 16; i -= 16 )
1133 {
1134 MULADDC_INIT
1135 MULADDC_CORE MULADDC_CORE
1136 MULADDC_CORE MULADDC_CORE
1137 MULADDC_CORE MULADDC_CORE
1138 MULADDC_CORE MULADDC_CORE
1139
1140 MULADDC_CORE MULADDC_CORE
1141 MULADDC_CORE MULADDC_CORE
1142 MULADDC_CORE MULADDC_CORE
1143 MULADDC_CORE MULADDC_CORE
1144 MULADDC_STOP
1145 }
1146
1147 for( ; i >= 8; i -= 8 )
1148 {
1149 MULADDC_INIT
1150 MULADDC_CORE MULADDC_CORE
1151 MULADDC_CORE MULADDC_CORE
1152
1153 MULADDC_CORE MULADDC_CORE
1154 MULADDC_CORE MULADDC_CORE
1155 MULADDC_STOP
1156 }
1157
1158 for( ; i > 0; i-- )
1159 {
1160 MULADDC_INIT
1161 MULADDC_CORE
1162 MULADDC_STOP
1163 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001164#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001165
1166 t++;
1167
1168 do {
1169 *d += c; c = ( *d < c ); d++;
1170 }
1171 while( c != 0 );
1172}
1173
1174/*
1175 * Baseline multiplication: X = A * B (HAC 14.12)
1176 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001177int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001178{
Paul Bakker23986e52011-04-24 08:57:21 +00001179 int ret;
1180 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001181 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001182
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001183 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001185 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1186 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001187
Paul Bakker23986e52011-04-24 08:57:21 +00001188 for( i = A->n; i > 0; i-- )
1189 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001190 break;
1191
Paul Bakker23986e52011-04-24 08:57:21 +00001192 for( j = B->n; j > 0; j-- )
1193 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001194 break;
1195
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001196 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1197 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001198
Paul Bakker23986e52011-04-24 08:57:21 +00001199 for( i++; j > 0; j-- )
1200 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001201
1202 X->s = A->s * B->s;
1203
1204cleanup:
1205
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001206 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001207
1208 return( ret );
1209}
1210
1211/*
1212 * Baseline multiplication: X = A * b
1213 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001214int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001215{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001216 mbedtls_mpi _B;
1217 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001218
1219 _B.s = 1;
1220 _B.n = 1;
1221 _B.p = p;
1222 p[0] = b;
1223
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001224 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001225}
1226
1227/*
Simon Butcher7ebe2782015-12-28 00:05:30 +00001228 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1229 * mbedtls_mpi_uint divisor, d
Simon Butcherea303e32015-11-26 23:43:34 +00001230 */
Simon Butcher7ebe2782015-12-28 00:05:30 +00001231static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1232 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcherea303e32015-11-26 23:43:34 +00001233{
Manuel Pégourié-Gonnard5a8396e2015-12-01 10:27:00 +01001234#if defined(MBEDTLS_HAVE_UDBL)
1235 mbedtls_t_udbl dividend, quotient;
Simon Butcher7ebe2782015-12-28 00:05:30 +00001236#else
Simon Butcher61891752016-01-03 00:24:34 +00001237 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1238 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcher7ebe2782015-12-28 00:05:30 +00001239 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1240 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher61891752016-01-03 00:24:34 +00001241 size_t s;
Manuel Pégourié-Gonnard5a8396e2015-12-01 10:27:00 +01001242#endif
1243
Simon Butcherea303e32015-11-26 23:43:34 +00001244 /*
1245 * Check for overflow
1246 */
Simon Butcher7ebe2782015-12-28 00:05:30 +00001247 if( 0 == d || u1 >= d )
Simon Butcherea303e32015-11-26 23:43:34 +00001248 {
Simon Butcher7ebe2782015-12-28 00:05:30 +00001249 if (r != NULL) *r = ~0;
Simon Butcherea303e32015-11-26 23:43:34 +00001250
Simon Butcher7ebe2782015-12-28 00:05:30 +00001251 return ( ~0 );
Simon Butcherea303e32015-11-26 23:43:34 +00001252 }
1253
1254#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcherea303e32015-11-26 23:43:34 +00001255 dividend = (mbedtls_t_udbl) u1 << biL;
1256 dividend |= (mbedtls_t_udbl) u0;
1257 quotient = dividend / d;
1258 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1259 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1260
1261 if( r != NULL )
Simon Butcher61891752016-01-03 00:24:34 +00001262 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcherea303e32015-11-26 23:43:34 +00001263
1264 return (mbedtls_mpi_uint) quotient;
1265#else
Simon Butcherea303e32015-11-26 23:43:34 +00001266
1267 /*
1268 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1269 * Vol. 2 - Seminumerical Algorithms, Knuth
1270 */
1271
1272 /*
1273 * Normalize the divisor, d, and dividend, u0, u1
1274 */
1275 s = mbedtls_clz( d );
1276 d = d << s;
1277
1278 u1 = u1 << s;
Simon Butcher61891752016-01-03 00:24:34 +00001279 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcherea303e32015-11-26 23:43:34 +00001280 u0 = u0 << s;
1281
1282 d1 = d >> biH;
Simon Butcher61891752016-01-03 00:24:34 +00001283 d0 = d & uint_halfword_mask;
Simon Butcherea303e32015-11-26 23:43:34 +00001284
1285 u0_msw = u0 >> biH;
Simon Butcher61891752016-01-03 00:24:34 +00001286 u0_lsw = u0 & uint_halfword_mask;
Simon Butcherea303e32015-11-26 23:43:34 +00001287
1288 /*
1289 * Find the first quotient and remainder
1290 */
1291 q1 = u1 / d1;
1292 r0 = u1 - d1 * q1;
1293
1294 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1295 {
1296 q1 -= 1;
1297 r0 += d1;
1298
1299 if ( r0 >= radix ) break;
1300 }
1301
Simon Butcher7ebe2782015-12-28 00:05:30 +00001302 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcherea303e32015-11-26 23:43:34 +00001303 q0 = rAX / d1;
1304 r0 = rAX - q0 * d1;
1305
1306 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1307 {
1308 q0 -= 1;
1309 r0 += d1;
1310
1311 if ( r0 >= radix ) break;
1312 }
1313
1314 if (r != NULL)
Simon Butcher7ebe2782015-12-28 00:05:30 +00001315 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcherea303e32015-11-26 23:43:34 +00001316
1317 quotient = q1 * radix + q0;
1318
1319 return quotient;
1320#endif
1321}
1322
1323/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001324 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001325 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001326int 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 +00001327{
Paul Bakker23986e52011-04-24 08:57:21 +00001328 int ret;
1329 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001330 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1333 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001335 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1336 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001338 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001339 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001340 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1341 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001342 return( 0 );
1343 }
1344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001345 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1346 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001347 X.s = Y.s = 1;
1348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001349 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1350 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1351 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1352 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001353
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001354 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001355 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001356 {
1357 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001358 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1359 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001360 }
1361 else k = 0;
1362
1363 n = X.n - 1;
1364 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001366
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001367 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001368 {
1369 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001370 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001371 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001373
1374 for( i = n; i > t ; i-- )
1375 {
1376 if( X.p[i] >= Y.p[t] )
1377 Z.p[i - t - 1] = ~0;
1378 else
1379 {
Simon Butcherea303e32015-11-26 23:43:34 +00001380 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1381 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001382 }
1383
1384 Z.p[i - t - 1]++;
1385 do
1386 {
1387 Z.p[i - t - 1]--;
1388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001389 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001390 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001391 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001393
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001394 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001395 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1396 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001397 T2.p[2] = X.p[i];
1398 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001400
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001401 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1402 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1403 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001404
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001405 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001406 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001407 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1408 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1409 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001410 Z.p[i - t - 1]--;
1411 }
1412 }
1413
1414 if( Q != NULL )
1415 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001416 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001417 Q->s = A->s * B->s;
1418 }
1419
1420 if( R != NULL )
1421 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001422 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001423 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001424 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001425
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001426 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001427 R->s = 1;
1428 }
1429
1430cleanup:
1431
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001432 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1433 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001434
1435 return( ret );
1436}
1437
1438/*
1439 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001440 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001441int 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 +00001442{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001443 mbedtls_mpi _B;
1444 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001445
1446 p[0] = ( b < 0 ) ? -b : b;
1447 _B.s = ( b < 0 ) ? -1 : 1;
1448 _B.n = 1;
1449 _B.p = p;
1450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001451 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001452}
1453
1454/*
1455 * Modulo: R = A mod B
1456 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001457int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001458{
1459 int ret;
1460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001461 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1462 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001463
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001464 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1467 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001468
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001469 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1470 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001471
1472cleanup:
1473
1474 return( ret );
1475}
1476
1477/*
1478 * Modulo: r = A mod b
1479 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001480int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001481{
Paul Bakker23986e52011-04-24 08:57:21 +00001482 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001483 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001484
1485 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001486 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001487
1488 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001489 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001490
1491 /*
1492 * handle trivial cases
1493 */
1494 if( b == 1 )
1495 {
1496 *r = 0;
1497 return( 0 );
1498 }
1499
1500 if( b == 2 )
1501 {
1502 *r = A->p[0] & 1;
1503 return( 0 );
1504 }
1505
1506 /*
1507 * general case
1508 */
Paul Bakker23986e52011-04-24 08:57:21 +00001509 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001510 {
Paul Bakker23986e52011-04-24 08:57:21 +00001511 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001512 y = ( y << biH ) | ( x >> biH );
1513 z = y / b;
1514 y -= z * b;
1515
1516 x <<= biH;
1517 y = ( y << biH ) | ( x >> biH );
1518 z = y / b;
1519 y -= z * b;
1520 }
1521
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001522 /*
1523 * If A is negative, then the current y represents a negative value.
1524 * Flipping it to the positive side.
1525 */
1526 if( A->s < 0 && y != 0 )
1527 y = b - y;
1528
Paul Bakker5121ce52009-01-03 21:22:43 +00001529 *r = y;
1530
1531 return( 0 );
1532}
1533
1534/*
1535 * Fast Montgomery initialization (thanks to Tom St Denis)
1536 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001537static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001538{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001540 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001541
1542 x = m0;
1543 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001544
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001545 for( i = biL; i >= 8; i /= 2 )
1546 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001547
1548 *mm = ~x + 1;
1549}
1550
1551/*
1552 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1553 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001554static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1555 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001556{
Paul Bakker23986e52011-04-24 08:57:21 +00001557 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001558 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001559
1560 memset( T->p, 0, T->n * ciL );
1561
1562 d = T->p;
1563 n = N->n;
1564 m = ( B->n < n ) ? B->n : n;
1565
1566 for( i = 0; i < n; i++ )
1567 {
1568 /*
1569 * T = (T + u0*B + u1*N) / 2^biL
1570 */
1571 u0 = A->p[i];
1572 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1573
1574 mpi_mul_hlp( m, B->p, d, u0 );
1575 mpi_mul_hlp( n, N->p, d, u1 );
1576
1577 *d++ = u0; d[n + 1] = 0;
1578 }
1579
Paul Bakker66d5d072014-06-17 16:39:18 +02001580 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001581
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001582 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001583 mpi_sub_hlp( n, N->p, A->p );
1584 else
1585 /* prevent timing attacks */
1586 mpi_sub_hlp( n, A->p, T->p );
1587}
1588
1589/*
1590 * Montgomery reduction: A = A * R^-1 mod N
1591 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001592static 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 +00001593{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001594 mbedtls_mpi_uint z = 1;
1595 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001596
Paul Bakker8ddb6452013-02-27 14:56:33 +01001597 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001598 U.p = &z;
1599
1600 mpi_montmul( A, &U, N, mm, T );
1601}
1602
1603/*
1604 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1605 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001606int 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 +00001607{
Paul Bakker23986e52011-04-24 08:57:21 +00001608 int ret;
1609 size_t wbits, wsize, one = 1;
1610 size_t i, j, nblimbs;
1611 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001612 mbedtls_mpi_uint ei, mm, state;
1613 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001614 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001615
Hanno Beckera82f8912017-11-06 15:08:27 +00001616 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001617 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001619 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1620 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001621
1622 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001623 * Init temps and window size
1624 */
1625 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001626 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1627 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001628 memset( W, 0, sizeof( W ) );
1629
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001630 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001631
1632 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1633 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001635 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1636 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001637
Paul Bakker5121ce52009-01-03 21:22:43 +00001638 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001639 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1640 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1641 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001642
1643 /*
Paul Bakker50546922012-05-19 08:40:49 +00001644 * Compensate for negative A (and correct at the end)
1645 */
1646 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001647 if( neg )
1648 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001649 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001650 Apos.s = 1;
1651 A = &Apos;
1652 }
1653
1654 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001655 * If 1st call, pre-compute R^2 mod N
1656 */
1657 if( _RR == NULL || _RR->p == NULL )
1658 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001659 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1660 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1661 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001662
1663 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001664 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001665 }
1666 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001667 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001668
1669 /*
1670 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1671 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001672 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1673 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001674 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001675 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001676
1677 mpi_montmul( &W[1], &RR, N, mm, &T );
1678
1679 /*
1680 * X = R^2 * R^-1 mod N = R mod N
1681 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001682 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001683 mpi_montred( X, N, mm, &T );
1684
1685 if( wsize > 1 )
1686 {
1687 /*
1688 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1689 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001690 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001692 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1693 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001694
1695 for( i = 0; i < wsize - 1; i++ )
1696 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001697
Paul Bakker5121ce52009-01-03 21:22:43 +00001698 /*
1699 * W[i] = W[i - 1] * W[1]
1700 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001701 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001702 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001703 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1704 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001705
1706 mpi_montmul( &W[i], &W[1], N, mm, &T );
1707 }
1708 }
1709
1710 nblimbs = E->n;
1711 bufsize = 0;
1712 nbits = 0;
1713 wbits = 0;
1714 state = 0;
1715
1716 while( 1 )
1717 {
1718 if( bufsize == 0 )
1719 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001720 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001721 break;
1722
Paul Bakker0d7702c2013-10-29 16:18:35 +01001723 nblimbs--;
1724
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001725 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001726 }
1727
1728 bufsize--;
1729
1730 ei = (E->p[nblimbs] >> bufsize) & 1;
1731
1732 /*
1733 * skip leading 0s
1734 */
1735 if( ei == 0 && state == 0 )
1736 continue;
1737
1738 if( ei == 0 && state == 1 )
1739 {
1740 /*
1741 * out of window, square X
1742 */
1743 mpi_montmul( X, X, N, mm, &T );
1744 continue;
1745 }
1746
1747 /*
1748 * add ei to current window
1749 */
1750 state = 2;
1751
1752 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001753 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001754
1755 if( nbits == wsize )
1756 {
1757 /*
1758 * X = X^wsize R^-1 mod N
1759 */
1760 for( i = 0; i < wsize; i++ )
1761 mpi_montmul( X, X, N, mm, &T );
1762
1763 /*
1764 * X = X * W[wbits] R^-1 mod N
1765 */
1766 mpi_montmul( X, &W[wbits], N, mm, &T );
1767
1768 state--;
1769 nbits = 0;
1770 wbits = 0;
1771 }
1772 }
1773
1774 /*
1775 * process the remaining bits
1776 */
1777 for( i = 0; i < nbits; i++ )
1778 {
1779 mpi_montmul( X, X, N, mm, &T );
1780
1781 wbits <<= 1;
1782
Paul Bakker66d5d072014-06-17 16:39:18 +02001783 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001784 mpi_montmul( X, &W[1], N, mm, &T );
1785 }
1786
1787 /*
1788 * X = A^E * R * R^-1 mod N = A^E mod N
1789 */
1790 mpi_montred( X, N, mm, &T );
1791
Hanno Becker2a8d6552017-04-18 09:07:45 +01001792 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001793 {
1794 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001795 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001796 }
1797
Paul Bakker5121ce52009-01-03 21:22:43 +00001798cleanup:
1799
Paul Bakker66d5d072014-06-17 16:39:18 +02001800 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001801 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001802
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001803 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001804
Paul Bakker75a28602014-03-31 12:08:17 +02001805 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001806 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001807
1808 return( ret );
1809}
1810
Paul Bakker5121ce52009-01-03 21:22:43 +00001811/*
1812 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1813 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001814int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001815{
Paul Bakker23986e52011-04-24 08:57:21 +00001816 int ret;
1817 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001818 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001819
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001820 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001821
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001822 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1823 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001824
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001825 lz = mbedtls_mpi_lsb( &TA );
1826 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001827
Paul Bakker66d5d072014-06-17 16:39:18 +02001828 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001829 lz = lzt;
1830
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001831 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1832 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001833
Paul Bakker5121ce52009-01-03 21:22:43 +00001834 TA.s = TB.s = 1;
1835
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001836 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001837 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001838 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1839 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001840
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001841 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001842 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001843 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1844 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001845 }
1846 else
1847 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001848 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1849 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001850 }
1851 }
1852
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001853 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1854 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001855
1856cleanup:
1857
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001858 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001859
1860 return( ret );
1861}
1862
Paul Bakker33dc46b2014-04-30 16:11:39 +02001863/*
1864 * Fill X with size bytes of random.
1865 *
1866 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001867 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001868 * deterministic, eg for tests).
1869 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001870int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001871 int (*f_rng)(void *, unsigned char *, size_t),
1872 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001873{
Paul Bakker23986e52011-04-24 08:57:21 +00001874 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001875 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001876
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001877 if( size > MBEDTLS_MPI_MAX_SIZE )
1878 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001879
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1881 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001882
1883cleanup:
Hanno Becker0f49bbc2017-10-18 12:41:30 +01001884 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001885 return( ret );
1886}
1887
Paul Bakker5121ce52009-01-03 21:22:43 +00001888/*
1889 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1890 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001891int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001892{
1893 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001895
Hanno Becker2938ccb2017-04-18 15:49:39 +01001896 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001897 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001898
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001899 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1900 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1901 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001902
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001903 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001904
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001905 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001906 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001907 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001908 goto cleanup;
1909 }
1910
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001911 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1912 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1913 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1914 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001915
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001916 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1917 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1918 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1919 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001920
1921 do
1922 {
1923 while( ( TU.p[0] & 1 ) == 0 )
1924 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001925 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001926
1927 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1928 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1930 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001931 }
1932
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001933 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1934 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001935 }
1936
1937 while( ( TV.p[0] & 1 ) == 0 )
1938 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001939 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001940
1941 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1942 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001943 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1944 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945 }
1946
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001947 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1948 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001949 }
1950
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001951 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001952 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001953 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1954 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1955 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956 }
1957 else
1958 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1960 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1961 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001962 }
1963 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001964 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001965
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001966 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1967 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001968
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001969 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1970 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001971
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001972 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001973
1974cleanup:
1975
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001976 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1977 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1978 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001979
1980 return( ret );
1981}
1982
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001983#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001984
Paul Bakker5121ce52009-01-03 21:22:43 +00001985static const int small_prime[] =
1986{
1987 3, 5, 7, 11, 13, 17, 19, 23,
1988 29, 31, 37, 41, 43, 47, 53, 59,
1989 61, 67, 71, 73, 79, 83, 89, 97,
1990 101, 103, 107, 109, 113, 127, 131, 137,
1991 139, 149, 151, 157, 163, 167, 173, 179,
1992 181, 191, 193, 197, 199, 211, 223, 227,
1993 229, 233, 239, 241, 251, 257, 263, 269,
1994 271, 277, 281, 283, 293, 307, 311, 313,
1995 317, 331, 337, 347, 349, 353, 359, 367,
1996 373, 379, 383, 389, 397, 401, 409, 419,
1997 421, 431, 433, 439, 443, 449, 457, 461,
1998 463, 467, 479, 487, 491, 499, 503, 509,
1999 521, 523, 541, 547, 557, 563, 569, 571,
2000 577, 587, 593, 599, 601, 607, 613, 617,
2001 619, 631, 641, 643, 647, 653, 659, 661,
2002 673, 677, 683, 691, 701, 709, 719, 727,
2003 733, 739, 743, 751, 757, 761, 769, 773,
2004 787, 797, 809, 811, 821, 823, 827, 829,
2005 839, 853, 857, 859, 863, 877, 881, 883,
2006 887, 907, 911, 919, 929, 937, 941, 947,
2007 953, 967, 971, 977, 983, 991, 997, -103
2008};
2009
2010/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002011 * Small divisors test (X must be positive)
2012 *
2013 * Return values:
2014 * 0: no small factor (possible prime, more tests needed)
2015 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002017 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002018 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002019static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002020{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002021 int ret = 0;
2022 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002024
Paul Bakker5121ce52009-01-03 21:22:43 +00002025 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002026 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002027
2028 for( i = 0; small_prime[i] > 0; i++ )
2029 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002030 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002031 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002032
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002033 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002034
2035 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002036 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002037 }
2038
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002039cleanup:
2040 return( ret );
2041}
2042
2043/*
2044 * Miller-Rabin pseudo-primality test (HAC 4.24)
2045 */
Janos Follath9dc5b7a2018-09-03 14:45:23 +01002046static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002047 int (*f_rng)(void *, unsigned char *, size_t),
2048 void *p_rng )
2049{
Pascal Junodb99183d2015-03-11 16:49:45 +01002050 int ret, count;
Janos Follath9dc5b7a2018-09-03 14:45:23 +01002051 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002053
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002054 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2055 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002056
Paul Bakker5121ce52009-01-03 21:22:43 +00002057 /*
2058 * W = |X| - 1
2059 * R = W >> lsb( W )
2060 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002061 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2062 s = mbedtls_mpi_lsb( &W );
2063 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2064 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002065
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002066 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00002067
Janos Follath9dc5b7a2018-09-03 14:45:23 +01002068 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002069 {
2070 /*
2071 * pick a random A, 1 < A < |X| - 1
2072 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002073 count = 0;
2074 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002075 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002076
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002077 j = mbedtls_mpi_bitlen( &A );
2078 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002079 if (j > k) {
Darryl Green0c9bbb02018-10-02 13:21:35 +01002080 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002081 }
2082
2083 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002084 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002085 }
2086
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002087 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2088 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002089
2090 /*
2091 * A = A^R mod |X|
2092 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002093 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002094
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002095 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2096 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002097 continue;
2098
2099 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002100 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002101 {
2102 /*
2103 * A = A * A mod |X|
2104 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002105 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2106 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002107
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002108 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002109 break;
2110
2111 j++;
2112 }
2113
2114 /*
2115 * not prime if A != |X| - 1 or A == 1
2116 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002117 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2118 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002119 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002120 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002121 break;
2122 }
2123 }
2124
2125cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002126 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2127 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002128
2129 return( ret );
2130}
2131
2132/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002133 * Pseudo-primality test: small factors, then Miller-Rabin
2134 */
Darryl Green73497ce2018-10-16 15:07:48 +01002135static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002136 int (*f_rng)(void *, unsigned char *, size_t),
2137 void *p_rng )
2138{
2139 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002140 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002141
2142 XX.s = 1;
2143 XX.n = X->n;
2144 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002145
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002146 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2147 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2148 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002149
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002150 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002151 return( 0 );
2152
2153 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2154 {
2155 if( ret == 1 )
2156 return( 0 );
2157
2158 return( ret );
2159 }
2160
Janos Follath9dc5b7a2018-09-03 14:45:23 +01002161 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2162}
2163
2164/*
2165 * Pseudo-primality test, error probability 2^-80
2166 */
2167int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2168 int (*f_rng)(void *, unsigned char *, size_t),
2169 void *p_rng )
2170{
2171 return mpi_is_prime_internal( X, 40, f_rng, p_rng );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002172}
2173
2174/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002175 * Prime number generation
2176 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002178 int (*f_rng)(void *, unsigned char *, size_t),
2179 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002180{
Paul Bakker23986e52011-04-24 08:57:21 +00002181 int ret;
2182 size_t k, n;
Janos Follath9dc5b7a2018-09-03 14:45:23 +01002183 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184 mbedtls_mpi_uint r;
2185 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002186
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002187 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2188 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002189
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002190 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002191
2192 n = BITS_TO_LIMBS( nbits );
2193
Janos Follath9dc5b7a2018-09-03 14:45:23 +01002194 /*
2195 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2196 */
2197 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2198 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2199 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002201 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002202
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002203 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002204 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002205
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002206 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002207
2208 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002209
2210 if( dh_flag == 0 )
2211 {
Janos Follath9dc5b7a2018-09-03 14:45:23 +01002212 while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002213 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002214 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002215 goto cleanup;
2216
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002217 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002218 }
2219 }
2220 else
2221 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002222 /*
2223 * An necessary condition for Y and X = 2Y + 1 to be prime
2224 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2225 * Make sure it is satisfied, while keeping X = 3 mod 4
2226 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002227
2228 X->p[0] |= 2;
2229
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002230 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002231 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002232 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002233 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002234 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002235
2236 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002237 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2238 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002239
2240 while( 1 )
2241 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002242 /*
2243 * First, check small factors for X and Y
2244 * before doing Miller-Rabin on any of them
2245 */
2246 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2247 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follath9dc5b7a2018-09-03 14:45:23 +01002248 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
2249 == 0 &&
2250 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
2251 == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002252 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002253 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002254 }
2255
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002256 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002257 goto cleanup;
2258
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002259 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002260 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002261 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2262 * so up Y by 6 and X by 12.
2263 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2265 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002266 }
2267 }
2268
2269cleanup:
2270
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002271 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002272
2273 return( ret );
2274}
2275
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002276#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002277
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002278#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002279
Paul Bakker23986e52011-04-24 08:57:21 +00002280#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002281
2282static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2283{
2284 { 693, 609, 21 },
2285 { 1764, 868, 28 },
2286 { 768454923, 542167814, 1 }
2287};
2288
Paul Bakker5121ce52009-01-03 21:22:43 +00002289/*
2290 * Checkup routine
2291 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002292int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002293{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002294 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002295 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002296
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002297 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2298 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002299
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002300 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002301 "EFE021C2645FD1DC586E69184AF4A31E" \
2302 "D5F53E93B5F123FA41680867BA110131" \
2303 "944FE7952E2517337780CB0DB80E61AA" \
2304 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2305
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002306 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002307 "B2E7EFD37075B9F03FF989C7C5051C20" \
2308 "34D2A323810251127E7BF8625A4F49A5" \
2309 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2310 "5B5C25763222FEFCCFC38B832366C29E" ) );
2311
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002312 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002313 "0066A198186C18C10B2F5ED9B522752A" \
2314 "9830B69916E535C8F047518A889A43A5" \
2315 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2316
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002317 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002319 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002320 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2321 "9E857EA95A03512E2BAE7391688D264A" \
2322 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2323 "8001B72E848A38CAE1C65F78E56ABDEF" \
2324 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2325 "ECF677152EF804370C1A305CAF3B5BF1" \
2326 "30879B56C61DE584A0F53A2447A51E" ) );
2327
2328 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002329 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002330
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002331 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002332 {
2333 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002334 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002335
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002336 ret = 1;
2337 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002338 }
2339
2340 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002343 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002345 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002346 "256567336059E52CAE22925474705F39A94" ) );
2347
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002348 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002349 "6613F26162223DF488E9CD48CC132C7A" \
2350 "0AC93C701B001B092E4E5B9F73BCD27B" \
2351 "9EE50D0657C77F374E903CDFA4C642" ) );
2352
2353 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002354 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002355
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002356 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2357 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002358 {
2359 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002360 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002361
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002362 ret = 1;
2363 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002364 }
2365
2366 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002369 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002370
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002371 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002372 "36E139AEA55215609D2816998ED020BB" \
2373 "BD96C37890F65171D948E9BC7CBAA4D9" \
2374 "325D24D6A3C12710F10A09FA08AB87" ) );
2375
2376 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002377 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002379 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002380 {
2381 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002382 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002383
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002384 ret = 1;
2385 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002386 }
2387
2388 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002389 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002390
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002391 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002393 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002394 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2395 "C3DBA76456363A10869622EAC2DD84EC" \
2396 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2397
2398 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002399 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002400
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002401 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002402 {
2403 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002404 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002405
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002406 ret = 1;
2407 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002408 }
2409
2410 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002411 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002412
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002413 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002414 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002415
Paul Bakker66d5d072014-06-17 16:39:18 +02002416 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002417 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002418 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2419 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002420
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002421 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002422
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002423 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002424 {
2425 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002426 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002427
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002428 ret = 1;
2429 goto cleanup;
2430 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002431 }
2432
2433 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002435
Paul Bakker5121ce52009-01-03 21:22:43 +00002436cleanup:
2437
2438 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002439 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002440
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002441 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2442 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002443
2444 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002445 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002446
2447 return( ret );
2448}
2449
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002450#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002451
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002452#endif /* MBEDTLS_BIGNUM_C */