blob: 9c38117b07e5a356fbeaf7a18156e1bc0dfb62c0 [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 */
21/*
22 * This MPI implementation is based on:
23 *
24 * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
Simon Butcher334a87b2015-10-14 22:56:44 +010025 * http://www.stillhq.com/extracted/gnupg-api/mpi/
Paul Bakker5121ce52009-01-03 21:22:43 +000026 * http://math.libtomcrypt.com/files/tommath.pdf
27 */
28
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020029#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000030#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020031#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020033#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000034
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000036
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000037#include "mbedtls/bignum.h"
38#include "mbedtls/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000039
Rich Evans00ab4702015-02-06 13:43:58 +000040#include <string.h>
41
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020042#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000043#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020044#else
Rich Evans00ab4702015-02-06 13:43:58 +000045#include <stdio.h>
46#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020047#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020048#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020050#endif
51
Paul Bakker34617722014-06-13 17:20:13 +020052/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020053static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020054 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
55}
56
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000058#define biL (ciL << 3) /* bits in limb */
59#define biH (ciL << 2) /* half limb size */
60
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010061#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
62
Paul Bakker5121ce52009-01-03 21:22:43 +000063/*
64 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020065 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000066 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020067#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
68#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000069
70/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000071 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000072 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020073void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000074{
Paul Bakker6c591fa2011-05-05 11:49:20 +000075 if( X == NULL )
76 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000077
Paul Bakker6c591fa2011-05-05 11:49:20 +000078 X->s = 1;
79 X->n = 0;
80 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000081}
82
83/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000084 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000085 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020086void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000087{
Paul Bakker6c591fa2011-05-05 11:49:20 +000088 if( X == NULL )
89 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000090
Paul Bakker6c591fa2011-05-05 11:49:20 +000091 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +000092 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020093 mbedtls_zeroize( X->p, X->n * ciL );
94 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +000095 }
96
Paul Bakker6c591fa2011-05-05 11:49:20 +000097 X->s = 1;
98 X->n = 0;
99 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000100}
101
102/*
103 * Enlarge to the specified number of limbs
104 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200105int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000106{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200107 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000108
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200110 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000111
Paul Bakker5121ce52009-01-03 21:22:43 +0000112 if( X->n < nblimbs )
113 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200114 if( ( p = mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200115 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000116
Paul Bakker5121ce52009-01-03 21:22:43 +0000117 if( X->p != NULL )
118 {
119 memcpy( p, X->p, X->n * ciL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120 mbedtls_zeroize( X->p, X->n * ciL );
121 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000122 }
123
124 X->n = nblimbs;
125 X->p = p;
126 }
127
128 return( 0 );
129}
130
131/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100132 * Resize down as much as possible,
133 * while keeping at least the specified number of limbs
134 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100136{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100138 size_t i;
139
140 /* Actually resize up in this case */
141 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200142 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100143
144 for( i = X->n - 1; i > 0; i-- )
145 if( X->p[i] != 0 )
146 break;
147 i++;
148
149 if( i < nblimbs )
150 i = nblimbs;
151
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200152 if( ( p = mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200153 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100155 if( X->p != NULL )
156 {
157 memcpy( p, X->p, i * ciL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 mbedtls_zeroize( X->p, X->n * ciL );
159 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100160 }
161
162 X->n = i;
163 X->p = p;
164
165 return( 0 );
166}
167
168/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000169 * Copy the contents of Y into X
170 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000172{
Paul Bakker23986e52011-04-24 08:57:21 +0000173 int ret;
174 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000175
176 if( X == Y )
177 return( 0 );
178
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200179 if( Y->p == NULL )
180 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200182 return( 0 );
183 }
184
Paul Bakker5121ce52009-01-03 21:22:43 +0000185 for( i = Y->n - 1; i > 0; i-- )
186 if( Y->p[i] != 0 )
187 break;
188 i++;
189
190 X->s = Y->s;
191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200192 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000193
194 memset( X->p, 0, X->n * ciL );
195 memcpy( X->p, Y->p, i * ciL );
196
197cleanup:
198
199 return( ret );
200}
201
202/*
203 * Swap the contents of X and Y
204 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000206{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209 memcpy( &T, X, sizeof( mbedtls_mpi ) );
210 memcpy( X, Y, sizeof( mbedtls_mpi ) );
211 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000212}
213
214/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100215 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100216 * about whether the assignment was made or not.
217 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100218 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100220{
221 int ret = 0;
222 size_t i;
223
Pascal Junodb99183d2015-03-11 16:49:45 +0100224 /* make sure assign is 0 or 1 in a time-constant manner */
225 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200227 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100228
Paul Bakker66d5d072014-06-17 16:39:18 +0200229 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100230
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100231 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200232 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100233
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100234 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200235 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100236
237cleanup:
238 return( ret );
239}
240
241/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100242 * Conditionally swap X and Y, without leaking information
243 * about whether the swap was made or not.
244 * Here it is not ok to simply swap the pointers, which whould lead to
245 * different memory access patterns when X and Y are used afterwards.
246 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100248{
249 int ret, s;
250 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200251 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100252
253 if( X == Y )
254 return( 0 );
255
Pascal Junodb99183d2015-03-11 16:49:45 +0100256 /* make sure swap is 0 or 1 in a time-constant manner */
257 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
260 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100261
262 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200263 X->s = X->s * ( 1 - swap ) + Y->s * swap;
264 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100265
266
267 for( i = 0; i < X->n; i++ )
268 {
269 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200270 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
271 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100272 }
273
274cleanup:
275 return( ret );
276}
277
278/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000279 * Set value from integer
280 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000282{
283 int ret;
284
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200285 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000286 memset( X->p, 0, X->n * ciL );
287
288 X->p[0] = ( z < 0 ) ? -z : z;
289 X->s = ( z < 0 ) ? -1 : 1;
290
291cleanup:
292
293 return( ret );
294}
295
296/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000297 * Get a specific bit
298 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000300{
301 if( X->n * biL <= pos )
302 return( 0 );
303
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200304 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000305}
306
307/*
308 * Set a bit to a specific value of 0 or 1
309 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200310int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000311{
312 int ret = 0;
313 size_t off = pos / biL;
314 size_t idx = pos % biL;
315
316 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200317 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200318
Paul Bakker2f5947e2011-05-18 15:47:11 +0000319 if( X->n * biL <= pos )
320 {
321 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200322 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200324 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000325 }
326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
328 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000329
330cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200331
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332 return( ret );
333}
334
335/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200336 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000337 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200338size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000339{
Paul Bakker23986e52011-04-24 08:57:21 +0000340 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000341
342 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000343 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000344 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
345 return( count );
346
347 return( 0 );
348}
349
350/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200351 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000352 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200353size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000354{
Paul Bakker23986e52011-04-24 08:57:21 +0000355 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000356
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200357 if( X->n == 0 )
358 return( 0 );
359
Paul Bakker5121ce52009-01-03 21:22:43 +0000360 for( i = X->n - 1; i > 0; i-- )
361 if( X->p[i] != 0 )
362 break;
363
Paul Bakker23986e52011-04-24 08:57:21 +0000364 for( j = biL; j > 0; j-- )
365 if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000366 break;
367
Paul Bakker23986e52011-04-24 08:57:21 +0000368 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000369}
370
371/*
372 * Return the total size in bytes
373 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200374size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000375{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200376 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000377}
378
379/*
380 * Convert an ASCII character to digit value
381 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000383{
384 *d = 255;
385
386 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
387 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
388 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200390 if( *d >= (mbedtls_mpi_uint) radix )
391 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000392
393 return( 0 );
394}
395
396/*
397 * Import from an ASCII string
398 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000400{
Paul Bakker23986e52011-04-24 08:57:21 +0000401 int ret;
402 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200403 mbedtls_mpi_uint d;
404 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000405
406 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000410
Paul Bakkerff60ee62010-03-16 21:09:09 +0000411 slen = strlen( s );
412
Paul Bakker5121ce52009-01-03 21:22:43 +0000413 if( radix == 16 )
414 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100415 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200416 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
417
Paul Bakkerff60ee62010-03-16 21:09:09 +0000418 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000419
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200420 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
421 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000422
Paul Bakker23986e52011-04-24 08:57:21 +0000423 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000424 {
Paul Bakker23986e52011-04-24 08:57:21 +0000425 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000426 {
427 X->s = -1;
428 break;
429 }
430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200431 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200432 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000433 }
434 }
435 else
436 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000438
Paul Bakkerff60ee62010-03-16 21:09:09 +0000439 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000440 {
441 if( i == 0 && s[i] == '-' )
442 {
443 X->s = -1;
444 continue;
445 }
446
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200447 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
448 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000449
450 if( X->s == 1 )
451 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000453 }
454 else
455 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000457 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 }
459 }
460
461cleanup:
462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000464
465 return( ret );
466}
467
468/*
469 * Helper to write the digits high-order first
470 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000472{
473 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000475
476 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000478
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
480 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
483 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000484
485 if( r < 10 )
486 *(*p)++ = (char)( r + 0x30 );
487 else
488 *(*p)++ = (char)( r + 0x37 );
489
490cleanup:
491
492 return( ret );
493}
494
495/*
496 * Export into an ASCII string
497 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100498int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
499 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000500{
Paul Bakker23986e52011-04-24 08:57:21 +0000501 int ret = 0;
502 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000503 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000505
506 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000508
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200509 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000510 if( radix >= 4 ) n >>= 1;
511 if( radix >= 16 ) n >>= 1;
512 n += 3;
513
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100514 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000515 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100516 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000518 }
519
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100520 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000522
523 if( X->s == -1 )
524 *p++ = '-';
525
526 if( radix == 16 )
527 {
Paul Bakker23986e52011-04-24 08:57:21 +0000528 int c;
529 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000530
Paul Bakker23986e52011-04-24 08:57:21 +0000531 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000532 {
Paul Bakker23986e52011-04-24 08:57:21 +0000533 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000534 {
Paul Bakker23986e52011-04-24 08:57:21 +0000535 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000536
Paul Bakker6c343d72014-07-10 14:36:19 +0200537 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000538 continue;
539
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000540 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000541 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000542 k = 1;
543 }
544 }
545 }
546 else
547 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200548 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000549
550 if( T.s == -1 )
551 T.s = 1;
552
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000554 }
555
556 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100557 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000558
559cleanup:
560
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200561 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000562
563 return( ret );
564}
565
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000567/*
568 * Read X from an opened file
569 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200570int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000571{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200572 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000573 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000574 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000575 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000576 * Buffer should have space for (short) label and decimal formatted MPI,
577 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000578 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200579 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000580
581 memset( s, 0, sizeof( s ) );
582 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200583 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
585 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000586 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200587 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000588
Paul Bakker5121ce52009-01-03 21:22:43 +0000589 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
590 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
591
592 p = s + slen;
593 while( --p >= s )
594 if( mpi_get_digit( &d, radix, *p ) != 0 )
595 break;
596
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000598}
599
600/*
601 * Write X into an opened file (or stdout if fout == NULL)
602 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000604{
Paul Bakker23986e52011-04-24 08:57:21 +0000605 int ret;
606 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000607 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000608 * Buffer should have space for (short) label and decimal formatted MPI,
609 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000610 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000612
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100613 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000614
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100615 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000616
617 if( p == NULL ) p = "";
618
619 plen = strlen( p );
620 slen = strlen( s );
621 s[slen++] = '\r';
622 s[slen++] = '\n';
623
624 if( fout != NULL )
625 {
626 if( fwrite( p, 1, plen, fout ) != plen ||
627 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000629 }
630 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000632
633cleanup:
634
635 return( ret );
636}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000638
639/*
640 * Import X from unsigned binary data, big endian
641 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000643{
Paul Bakker23986e52011-04-24 08:57:21 +0000644 int ret;
645 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000646
647 for( n = 0; n < buflen; n++ )
648 if( buf[n] != 0 )
649 break;
650
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
652 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000653
Paul Bakker23986e52011-04-24 08:57:21 +0000654 for( i = buflen, j = 0; i > n; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000656
657cleanup:
658
659 return( ret );
660}
661
662/*
663 * Export X into unsigned binary data, big endian
664 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000666{
Paul Bakker23986e52011-04-24 08:57:21 +0000667 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000670
671 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000673
674 memset( buf, 0, buflen );
675
676 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
677 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
678
679 return( 0 );
680}
681
682/*
683 * Left-shift: X <<= count
684 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000686{
Paul Bakker23986e52011-04-24 08:57:21 +0000687 int ret;
688 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000690
691 v0 = count / (biL );
692 t1 = count & (biL - 1);
693
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200694 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000695
Paul Bakkerf9688572011-05-05 10:00:45 +0000696 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
699 ret = 0;
700
701 /*
702 * shift by count / limb_size
703 */
704 if( v0 > 0 )
705 {
Paul Bakker23986e52011-04-24 08:57:21 +0000706 for( i = X->n; i > v0; i-- )
707 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000708
Paul Bakker23986e52011-04-24 08:57:21 +0000709 for( ; i > 0; i-- )
710 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000711 }
712
713 /*
714 * shift by count % limb_size
715 */
716 if( t1 > 0 )
717 {
718 for( i = v0; i < X->n; i++ )
719 {
720 r1 = X->p[i] >> (biL - t1);
721 X->p[i] <<= t1;
722 X->p[i] |= r0;
723 r0 = r1;
724 }
725 }
726
727cleanup:
728
729 return( ret );
730}
731
732/*
733 * Right-shift: X >>= count
734 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200735int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000736{
Paul Bakker23986e52011-04-24 08:57:21 +0000737 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200738 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000739
740 v0 = count / biL;
741 v1 = count & (biL - 1);
742
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100743 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200744 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100745
Paul Bakker5121ce52009-01-03 21:22:43 +0000746 /*
747 * shift by count / limb_size
748 */
749 if( v0 > 0 )
750 {
751 for( i = 0; i < X->n - v0; i++ )
752 X->p[i] = X->p[i + v0];
753
754 for( ; i < X->n; i++ )
755 X->p[i] = 0;
756 }
757
758 /*
759 * shift by count % limb_size
760 */
761 if( v1 > 0 )
762 {
Paul Bakker23986e52011-04-24 08:57:21 +0000763 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000764 {
Paul Bakker23986e52011-04-24 08:57:21 +0000765 r1 = X->p[i - 1] << (biL - v1);
766 X->p[i - 1] >>= v1;
767 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000768 r0 = r1;
769 }
770 }
771
772 return( 0 );
773}
774
775/*
776 * Compare unsigned values
777 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200778int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000779{
Paul Bakker23986e52011-04-24 08:57:21 +0000780 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000781
Paul Bakker23986e52011-04-24 08:57:21 +0000782 for( i = X->n; i > 0; i-- )
783 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000784 break;
785
Paul Bakker23986e52011-04-24 08:57:21 +0000786 for( j = Y->n; j > 0; j-- )
787 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000788 break;
789
Paul Bakker23986e52011-04-24 08:57:21 +0000790 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000791 return( 0 );
792
793 if( i > j ) return( 1 );
794 if( j > i ) return( -1 );
795
Paul Bakker23986e52011-04-24 08:57:21 +0000796 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000797 {
Paul Bakker23986e52011-04-24 08:57:21 +0000798 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
799 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000800 }
801
802 return( 0 );
803}
804
805/*
806 * Compare signed values
807 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200808int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000809{
Paul Bakker23986e52011-04-24 08:57:21 +0000810 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000811
Paul Bakker23986e52011-04-24 08:57:21 +0000812 for( i = X->n; i > 0; i-- )
813 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000814 break;
815
Paul Bakker23986e52011-04-24 08:57:21 +0000816 for( j = Y->n; j > 0; j-- )
817 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000818 break;
819
Paul Bakker23986e52011-04-24 08:57:21 +0000820 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000821 return( 0 );
822
823 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000824 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000825
826 if( X->s > 0 && Y->s < 0 ) return( 1 );
827 if( Y->s > 0 && X->s < 0 ) return( -1 );
828
Paul Bakker23986e52011-04-24 08:57:21 +0000829 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000830 {
Paul Bakker23986e52011-04-24 08:57:21 +0000831 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
832 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000833 }
834
835 return( 0 );
836}
837
838/*
839 * Compare signed values
840 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200841int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000842{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200843 mbedtls_mpi Y;
844 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000845
846 *p = ( z < 0 ) ? -z : z;
847 Y.s = ( z < 0 ) ? -1 : 1;
848 Y.n = 1;
849 Y.p = p;
850
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200851 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000852}
853
854/*
855 * Unsigned addition: X = |A| + |B| (HAC 14.7)
856 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200857int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000858{
Paul Bakker23986e52011-04-24 08:57:21 +0000859 int ret;
860 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200861 mbedtls_mpi_uint *o, *p, c;
Janos Follath3fc644f2015-10-25 14:24:10 +0100862 mbedtls_mpi TB;
Paul Bakker5121ce52009-01-03 21:22:43 +0000863
864 if( X == B )
865 {
Janos Follath3fc644f2015-10-25 14:24:10 +0100866 B = A; A = X;
867
Janos Follath6cbacec2015-10-25 12:29:13 +0100868 if( B == A )
869 {
870 // Making a temporary copy instead of shifting by one to deny
871 // the possibility of corresponding side-channel attacks.
Janos Follath6cbacec2015-10-25 12:29:13 +0100872 mbedtls_mpi_init( &TB );
873 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
874
Janos Follath3fc644f2015-10-25 14:24:10 +0100875 B = &TB;
Janos Follath6cbacec2015-10-25 12:29:13 +0100876 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000877 }
878
879 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200880 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200881
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000882 /*
883 * X should always be positive as a result of unsigned additions.
884 */
885 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000886
Paul Bakker23986e52011-04-24 08:57:21 +0000887 for( j = B->n; j > 0; j-- )
888 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000889 break;
890
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200891 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000892
893 o = B->p; p = X->p; c = 0;
894
Paul Bakker23986e52011-04-24 08:57:21 +0000895 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000896 {
897 *p += c; c = ( *p < c );
898 *p += *o; c += ( *p < *o );
899 }
900
901 while( c != 0 )
902 {
903 if( i >= X->n )
904 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200905 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000906 p = X->p + i;
907 }
908
Paul Bakker2d319fd2012-09-16 21:34:26 +0000909 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000910 }
911
912cleanup:
Janos Follath3fc644f2015-10-25 14:24:10 +0100913 if( &TB == B )
914 {
915 mbedtls_mpi_free( &TB );
916 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000917
918 return( ret );
919}
920
921/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200922 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000923 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200924static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000925{
Paul Bakker23986e52011-04-24 08:57:21 +0000926 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200927 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000928
929 for( i = c = 0; i < n; i++, s++, d++ )
930 {
931 z = ( *d < c ); *d -= c;
932 c = ( *d < *s ) + z; *d -= *s;
933 }
934
935 while( c != 0 )
936 {
937 z = ( *d < c ); *d -= c;
938 c = z; i++; d++;
939 }
940}
941
942/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100943 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000944 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200945int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000946{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000948 int ret;
949 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000950
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200951 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
952 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000953
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200954 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000955
956 if( X == B )
957 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200958 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000959 B = &TB;
960 }
961
962 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200963 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000964
Paul Bakker1ef7a532009-06-20 10:50:55 +0000965 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100966 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000967 */
968 X->s = 1;
969
Paul Bakker5121ce52009-01-03 21:22:43 +0000970 ret = 0;
971
Paul Bakker23986e52011-04-24 08:57:21 +0000972 for( n = B->n; n > 0; n-- )
973 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000974 break;
975
Paul Bakker23986e52011-04-24 08:57:21 +0000976 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000977
978cleanup:
979
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200980 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000981
982 return( ret );
983}
984
985/*
986 * Signed addition: X = A + B
987 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200988int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000989{
990 int ret, s = A->s;
991
992 if( A->s * B->s < 0 )
993 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200994 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000995 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200996 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000997 X->s = s;
998 }
999 else
1000 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001001 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001002 X->s = -s;
1003 }
1004 }
1005 else
1006 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001007 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001008 X->s = s;
1009 }
1010
1011cleanup:
1012
1013 return( ret );
1014}
1015
1016/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001017 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001018 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001020{
1021 int ret, s = A->s;
1022
1023 if( A->s * B->s > 0 )
1024 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001025 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001026 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001027 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001028 X->s = s;
1029 }
1030 else
1031 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001032 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001033 X->s = -s;
1034 }
1035 }
1036 else
1037 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001038 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001039 X->s = s;
1040 }
1041
1042cleanup:
1043
1044 return( ret );
1045}
1046
1047/*
1048 * Signed addition: X = A + b
1049 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001051{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001052 mbedtls_mpi _B;
1053 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001054
1055 p[0] = ( b < 0 ) ? -b : b;
1056 _B.s = ( b < 0 ) ? -1 : 1;
1057 _B.n = 1;
1058 _B.p = p;
1059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001060 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001061}
1062
1063/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001064 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001065 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001066int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001067{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001068 mbedtls_mpi _B;
1069 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001070
1071 p[0] = ( b < 0 ) ? -b : b;
1072 _B.s = ( b < 0 ) ? -1 : 1;
1073 _B.n = 1;
1074 _B.p = p;
1075
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001076 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001077}
1078
1079/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001080 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001081 */
1082static
1083#if defined(__APPLE__) && defined(__arm__)
1084/*
1085 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1086 * appears to need this to prevent bad ARM code generation at -O3.
1087 */
1088__attribute__ ((noinline))
1089#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001090void 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 +00001091{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001092 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001093
1094#if defined(MULADDC_HUIT)
1095 for( ; i >= 8; i -= 8 )
1096 {
1097 MULADDC_INIT
1098 MULADDC_HUIT
1099 MULADDC_STOP
1100 }
1101
1102 for( ; i > 0; i-- )
1103 {
1104 MULADDC_INIT
1105 MULADDC_CORE
1106 MULADDC_STOP
1107 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001108#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001109 for( ; i >= 16; i -= 16 )
1110 {
1111 MULADDC_INIT
1112 MULADDC_CORE MULADDC_CORE
1113 MULADDC_CORE MULADDC_CORE
1114 MULADDC_CORE MULADDC_CORE
1115 MULADDC_CORE MULADDC_CORE
1116
1117 MULADDC_CORE MULADDC_CORE
1118 MULADDC_CORE MULADDC_CORE
1119 MULADDC_CORE MULADDC_CORE
1120 MULADDC_CORE MULADDC_CORE
1121 MULADDC_STOP
1122 }
1123
1124 for( ; i >= 8; i -= 8 )
1125 {
1126 MULADDC_INIT
1127 MULADDC_CORE MULADDC_CORE
1128 MULADDC_CORE MULADDC_CORE
1129
1130 MULADDC_CORE MULADDC_CORE
1131 MULADDC_CORE MULADDC_CORE
1132 MULADDC_STOP
1133 }
1134
1135 for( ; i > 0; i-- )
1136 {
1137 MULADDC_INIT
1138 MULADDC_CORE
1139 MULADDC_STOP
1140 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001141#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001142
1143 t++;
1144
1145 do {
1146 *d += c; c = ( *d < c ); d++;
1147 }
1148 while( c != 0 );
1149}
1150
1151/*
1152 * Baseline multiplication: X = A * B (HAC 14.12)
1153 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001154int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001155{
Paul Bakker23986e52011-04-24 08:57:21 +00001156 int ret;
1157 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001158 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001160 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001161
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001162 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1163 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001164
Paul Bakker23986e52011-04-24 08:57:21 +00001165 for( i = A->n; i > 0; i-- )
1166 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001167 break;
1168
Paul Bakker23986e52011-04-24 08:57:21 +00001169 for( j = B->n; j > 0; j-- )
1170 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001171 break;
1172
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001173 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1174 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001175
Paul Bakker23986e52011-04-24 08:57:21 +00001176 for( i++; j > 0; j-- )
1177 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001178
1179 X->s = A->s * B->s;
1180
1181cleanup:
1182
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001183 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001184
1185 return( ret );
1186}
1187
1188/*
1189 * Baseline multiplication: X = A * b
1190 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001191int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001192{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001193 mbedtls_mpi _B;
1194 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001195
1196 _B.s = 1;
1197 _B.n = 1;
1198 _B.p = p;
1199 p[0] = b;
1200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001201 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001202}
1203
1204/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001205 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001206 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001207int 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 +00001208{
Paul Bakker23986e52011-04-24 08:57:21 +00001209 int ret;
1210 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001211 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001212
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001213 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1214 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001215
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001216 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1217 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001218
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001219 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001220 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001221 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1222 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001223 return( 0 );
1224 }
1225
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001226 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1227 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001228 X.s = Y.s = 1;
1229
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001230 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1231 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1232 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1233 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001234
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001235 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001236 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001237 {
1238 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001239 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1240 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001241 }
1242 else k = 0;
1243
1244 n = X.n - 1;
1245 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001246 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001247
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001248 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001249 {
1250 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001251 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001252 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001253 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001254
1255 for( i = n; i > t ; i-- )
1256 {
1257 if( X.p[i] >= Y.p[t] )
1258 Z.p[i - t - 1] = ~0;
1259 else
1260 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001261#if defined(MBEDTLS_HAVE_UDBL)
1262 mbedtls_t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001264 r = (mbedtls_t_udbl) X.p[i] << biL;
1265 r |= (mbedtls_t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001266 r /= Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001267 if( r > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1268 r = ( (mbedtls_t_udbl) 1 << biL ) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001269
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001270 Z.p[i - t - 1] = (mbedtls_mpi_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001271#else
1272 /*
1273 * __udiv_qrnnd_c, from gmp/longlong.h
1274 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001275 mbedtls_mpi_uint q0, q1, r0, r1;
1276 mbedtls_mpi_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001277
1278 d = Y.p[t];
1279 d0 = ( d << biH ) >> biH;
1280 d1 = ( d >> biH );
1281
1282 q1 = X.p[i] / d1;
1283 r1 = X.p[i] - d1 * q1;
1284 r1 <<= biH;
1285 r1 |= ( X.p[i - 1] >> biH );
1286
1287 m = q1 * d0;
1288 if( r1 < m )
1289 {
1290 q1--, r1 += d;
1291 while( r1 >= d && r1 < m )
1292 q1--, r1 += d;
1293 }
1294 r1 -= m;
1295
1296 q0 = r1 / d1;
1297 r0 = r1 - d1 * q0;
1298 r0 <<= biH;
1299 r0 |= ( X.p[i - 1] << biH ) >> biH;
1300
1301 m = q0 * d0;
1302 if( r0 < m )
1303 {
1304 q0--, r0 += d;
1305 while( r0 >= d && r0 < m )
1306 q0--, r0 += d;
1307 }
1308 r0 -= m;
1309
1310 Z.p[i - t - 1] = ( q1 << biH ) | q0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001311#endif /* MBEDTLS_HAVE_UDBL && !64-bit Apple with Clang 5.0 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001312 }
1313
1314 Z.p[i - t - 1]++;
1315 do
1316 {
1317 Z.p[i - t - 1]--;
1318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001319 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001320 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001321 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001322 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001324 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001325 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1326 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001327 T2.p[2] = X.p[i];
1328 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001329 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001330
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001331 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1332 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1333 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001335 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001336 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001337 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1338 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1339 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001340 Z.p[i - t - 1]--;
1341 }
1342 }
1343
1344 if( Q != NULL )
1345 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001346 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001347 Q->s = A->s * B->s;
1348 }
1349
1350 if( R != NULL )
1351 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001352 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001353 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001354 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001355
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001356 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001357 R->s = 1;
1358 }
1359
1360cleanup:
1361
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001362 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1363 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001364
1365 return( ret );
1366}
1367
1368/*
1369 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001370 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001371int 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 +00001372{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001373 mbedtls_mpi _B;
1374 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001375
1376 p[0] = ( b < 0 ) ? -b : b;
1377 _B.s = ( b < 0 ) ? -1 : 1;
1378 _B.n = 1;
1379 _B.p = p;
1380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001381 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001382}
1383
1384/*
1385 * Modulo: R = A mod B
1386 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001387int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001388{
1389 int ret;
1390
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1392 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001393
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001394 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001396 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1397 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001398
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1400 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001401
1402cleanup:
1403
1404 return( ret );
1405}
1406
1407/*
1408 * Modulo: r = A mod b
1409 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001410int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001411{
Paul Bakker23986e52011-04-24 08:57:21 +00001412 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001413 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001414
1415 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001416 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001417
1418 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001419 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001420
1421 /*
1422 * handle trivial cases
1423 */
1424 if( b == 1 )
1425 {
1426 *r = 0;
1427 return( 0 );
1428 }
1429
1430 if( b == 2 )
1431 {
1432 *r = A->p[0] & 1;
1433 return( 0 );
1434 }
1435
1436 /*
1437 * general case
1438 */
Paul Bakker23986e52011-04-24 08:57:21 +00001439 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001440 {
Paul Bakker23986e52011-04-24 08:57:21 +00001441 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001442 y = ( y << biH ) | ( x >> biH );
1443 z = y / b;
1444 y -= z * b;
1445
1446 x <<= biH;
1447 y = ( y << biH ) | ( x >> biH );
1448 z = y / b;
1449 y -= z * b;
1450 }
1451
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001452 /*
1453 * If A is negative, then the current y represents a negative value.
1454 * Flipping it to the positive side.
1455 */
1456 if( A->s < 0 && y != 0 )
1457 y = b - y;
1458
Paul Bakker5121ce52009-01-03 21:22:43 +00001459 *r = y;
1460
1461 return( 0 );
1462}
1463
1464/*
1465 * Fast Montgomery initialization (thanks to Tom St Denis)
1466 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001467static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001468{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001469 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001470 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001471
1472 x = m0;
1473 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001474
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001475 for( i = biL; i >= 8; i /= 2 )
1476 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001477
1478 *mm = ~x + 1;
1479}
1480
1481/*
1482 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1483 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001484static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1485 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001486{
Paul Bakker23986e52011-04-24 08:57:21 +00001487 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001488 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001489
1490 memset( T->p, 0, T->n * ciL );
1491
1492 d = T->p;
1493 n = N->n;
1494 m = ( B->n < n ) ? B->n : n;
1495
1496 for( i = 0; i < n; i++ )
1497 {
1498 /*
1499 * T = (T + u0*B + u1*N) / 2^biL
1500 */
1501 u0 = A->p[i];
1502 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1503
1504 mpi_mul_hlp( m, B->p, d, u0 );
1505 mpi_mul_hlp( n, N->p, d, u1 );
1506
1507 *d++ = u0; d[n + 1] = 0;
1508 }
1509
Paul Bakker66d5d072014-06-17 16:39:18 +02001510 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001511
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001512 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001513 mpi_sub_hlp( n, N->p, A->p );
1514 else
1515 /* prevent timing attacks */
1516 mpi_sub_hlp( n, A->p, T->p );
1517}
1518
1519/*
1520 * Montgomery reduction: A = A * R^-1 mod N
1521 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001522static 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 +00001523{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001524 mbedtls_mpi_uint z = 1;
1525 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001526
Paul Bakker8ddb6452013-02-27 14:56:33 +01001527 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001528 U.p = &z;
1529
1530 mpi_montmul( A, &U, N, mm, T );
1531}
1532
1533/*
1534 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1535 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001536int 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 +00001537{
Paul Bakker23986e52011-04-24 08:57:21 +00001538 int ret;
1539 size_t wbits, wsize, one = 1;
1540 size_t i, j, nblimbs;
1541 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001542 mbedtls_mpi_uint ei, mm, state;
1543 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001544 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001545
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001546 if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
1547 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001548
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001549 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1550 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001551
1552 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001553 * Init temps and window size
1554 */
1555 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001556 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1557 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001558 memset( W, 0, sizeof( W ) );
1559
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001560 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001561
1562 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1563 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1564
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001565 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1566 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001567
Paul Bakker5121ce52009-01-03 21:22:43 +00001568 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001569 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1570 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1571 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001572
1573 /*
Paul Bakker50546922012-05-19 08:40:49 +00001574 * Compensate for negative A (and correct at the end)
1575 */
1576 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001577 if( neg )
1578 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001579 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001580 Apos.s = 1;
1581 A = &Apos;
1582 }
1583
1584 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001585 * If 1st call, pre-compute R^2 mod N
1586 */
1587 if( _RR == NULL || _RR->p == NULL )
1588 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001589 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1590 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1591 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001592
1593 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001594 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001595 }
1596 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001597 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001598
1599 /*
1600 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1601 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001602 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1603 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001604 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001605 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001606
1607 mpi_montmul( &W[1], &RR, N, mm, &T );
1608
1609 /*
1610 * X = R^2 * R^-1 mod N = R mod N
1611 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001612 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001613 mpi_montred( X, N, mm, &T );
1614
1615 if( wsize > 1 )
1616 {
1617 /*
1618 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1619 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001620 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001622 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1623 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001624
1625 for( i = 0; i < wsize - 1; i++ )
1626 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001627
Paul Bakker5121ce52009-01-03 21:22:43 +00001628 /*
1629 * W[i] = W[i - 1] * W[1]
1630 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001631 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001632 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001633 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1634 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001635
1636 mpi_montmul( &W[i], &W[1], N, mm, &T );
1637 }
1638 }
1639
1640 nblimbs = E->n;
1641 bufsize = 0;
1642 nbits = 0;
1643 wbits = 0;
1644 state = 0;
1645
1646 while( 1 )
1647 {
1648 if( bufsize == 0 )
1649 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001650 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001651 break;
1652
Paul Bakker0d7702c2013-10-29 16:18:35 +01001653 nblimbs--;
1654
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001655 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001656 }
1657
1658 bufsize--;
1659
1660 ei = (E->p[nblimbs] >> bufsize) & 1;
1661
1662 /*
1663 * skip leading 0s
1664 */
1665 if( ei == 0 && state == 0 )
1666 continue;
1667
1668 if( ei == 0 && state == 1 )
1669 {
1670 /*
1671 * out of window, square X
1672 */
1673 mpi_montmul( X, X, N, mm, &T );
1674 continue;
1675 }
1676
1677 /*
1678 * add ei to current window
1679 */
1680 state = 2;
1681
1682 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001683 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001684
1685 if( nbits == wsize )
1686 {
1687 /*
1688 * X = X^wsize R^-1 mod N
1689 */
1690 for( i = 0; i < wsize; i++ )
1691 mpi_montmul( X, X, N, mm, &T );
1692
1693 /*
1694 * X = X * W[wbits] R^-1 mod N
1695 */
1696 mpi_montmul( X, &W[wbits], N, mm, &T );
1697
1698 state--;
1699 nbits = 0;
1700 wbits = 0;
1701 }
1702 }
1703
1704 /*
1705 * process the remaining bits
1706 */
1707 for( i = 0; i < nbits; i++ )
1708 {
1709 mpi_montmul( X, X, N, mm, &T );
1710
1711 wbits <<= 1;
1712
Paul Bakker66d5d072014-06-17 16:39:18 +02001713 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001714 mpi_montmul( X, &W[1], N, mm, &T );
1715 }
1716
1717 /*
1718 * X = A^E * R * R^-1 mod N = A^E mod N
1719 */
1720 mpi_montred( X, N, mm, &T );
1721
Paul Bakkerf6198c12012-05-16 08:02:29 +00001722 if( neg )
1723 {
1724 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001725 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001726 }
1727
Paul Bakker5121ce52009-01-03 21:22:43 +00001728cleanup:
1729
Paul Bakker66d5d072014-06-17 16:39:18 +02001730 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001731 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001732
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001733 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001734
Paul Bakker75a28602014-03-31 12:08:17 +02001735 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001736 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001737
1738 return( ret );
1739}
1740
Paul Bakker5121ce52009-01-03 21:22:43 +00001741/*
1742 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1743 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001744int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001745{
Paul Bakker23986e52011-04-24 08:57:21 +00001746 int ret;
1747 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001748 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001749
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001750 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001751
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001752 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1753 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001754
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755 lz = mbedtls_mpi_lsb( &TA );
1756 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001757
Paul Bakker66d5d072014-06-17 16:39:18 +02001758 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001759 lz = lzt;
1760
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001761 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1762 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001763
Paul Bakker5121ce52009-01-03 21:22:43 +00001764 TA.s = TB.s = 1;
1765
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001766 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001767 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001768 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1769 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001770
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001771 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001772 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001773 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1774 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001775 }
1776 else
1777 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001778 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1779 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001780 }
1781 }
1782
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001783 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1784 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001785
1786cleanup:
1787
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001788 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001789
1790 return( ret );
1791}
1792
Paul Bakker33dc46b2014-04-30 16:11:39 +02001793/*
1794 * Fill X with size bytes of random.
1795 *
1796 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001797 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001798 * deterministic, eg for tests).
1799 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001800int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001801 int (*f_rng)(void *, unsigned char *, size_t),
1802 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001803{
Paul Bakker23986e52011-04-24 08:57:21 +00001804 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001805 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001806
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001807 if( size > MBEDTLS_MPI_MAX_SIZE )
1808 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001809
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001810 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1811 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001812
1813cleanup:
1814 return( ret );
1815}
1816
Paul Bakker5121ce52009-01-03 21:22:43 +00001817/*
1818 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1819 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001820int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001821{
1822 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001823 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001824
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001825 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 )
1826 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001827
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001828 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1829 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1830 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001831
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001832 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001833
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001834 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001835 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001836 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001837 goto cleanup;
1838 }
1839
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001840 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1841 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1842 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1843 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001844
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001845 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1846 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1847 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1848 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001849
1850 do
1851 {
1852 while( ( TU.p[0] & 1 ) == 0 )
1853 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001854 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001855
1856 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1857 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001858 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1859 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001860 }
1861
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001862 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1863 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001864 }
1865
1866 while( ( TV.p[0] & 1 ) == 0 )
1867 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001868 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001869
1870 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1871 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001872 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1873 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001874 }
1875
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001876 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1877 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001878 }
1879
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001881 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1883 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1884 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001885 }
1886 else
1887 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001888 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1889 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1890 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001891 }
1892 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001893 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001894
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001895 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1896 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001897
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001898 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1899 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001900
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001901 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001902
1903cleanup:
1904
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001905 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1906 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1907 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001908
1909 return( ret );
1910}
1911
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001912#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001913
Paul Bakker5121ce52009-01-03 21:22:43 +00001914static const int small_prime[] =
1915{
1916 3, 5, 7, 11, 13, 17, 19, 23,
1917 29, 31, 37, 41, 43, 47, 53, 59,
1918 61, 67, 71, 73, 79, 83, 89, 97,
1919 101, 103, 107, 109, 113, 127, 131, 137,
1920 139, 149, 151, 157, 163, 167, 173, 179,
1921 181, 191, 193, 197, 199, 211, 223, 227,
1922 229, 233, 239, 241, 251, 257, 263, 269,
1923 271, 277, 281, 283, 293, 307, 311, 313,
1924 317, 331, 337, 347, 349, 353, 359, 367,
1925 373, 379, 383, 389, 397, 401, 409, 419,
1926 421, 431, 433, 439, 443, 449, 457, 461,
1927 463, 467, 479, 487, 491, 499, 503, 509,
1928 521, 523, 541, 547, 557, 563, 569, 571,
1929 577, 587, 593, 599, 601, 607, 613, 617,
1930 619, 631, 641, 643, 647, 653, 659, 661,
1931 673, 677, 683, 691, 701, 709, 719, 727,
1932 733, 739, 743, 751, 757, 761, 769, 773,
1933 787, 797, 809, 811, 821, 823, 827, 829,
1934 839, 853, 857, 859, 863, 877, 881, 883,
1935 887, 907, 911, 919, 929, 937, 941, 947,
1936 953, 967, 971, 977, 983, 991, 997, -103
1937};
1938
1939/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001940 * Small divisors test (X must be positive)
1941 *
1942 * Return values:
1943 * 0: no small factor (possible prime, more tests needed)
1944 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001945 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001946 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00001947 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001948static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00001949{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001950 int ret = 0;
1951 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001952 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001953
Paul Bakker5121ce52009-01-03 21:22:43 +00001954 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001955 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956
1957 for( i = 0; small_prime[i] > 0; i++ )
1958 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001960 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001961
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001962 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001963
1964 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001965 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001966 }
1967
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001968cleanup:
1969 return( ret );
1970}
1971
1972/*
1973 * Miller-Rabin pseudo-primality test (HAC 4.24)
1974 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001975static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001976 int (*f_rng)(void *, unsigned char *, size_t),
1977 void *p_rng )
1978{
Pascal Junodb99183d2015-03-11 16:49:45 +01001979 int ret, count;
1980 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001981 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001982
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001983 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
1984 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001985
Paul Bakker5121ce52009-01-03 21:22:43 +00001986 /*
1987 * W = |X| - 1
1988 * R = W >> lsb( W )
1989 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001990 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
1991 s = mbedtls_mpi_lsb( &W );
1992 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
1993 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001994
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001995 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00001996 /*
1997 * HAC, table 4.4
1998 */
1999 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
2000 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
2001 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
2002
2003 for( i = 0; i < n; i++ )
2004 {
2005 /*
2006 * pick a random A, 1 < A < |X| - 1
2007 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002008 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002009
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002010 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00002011 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002012 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002013 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00002014 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002015 A.p[0] |= 3;
2016
Pascal Junodb99183d2015-03-11 16:49:45 +01002017 count = 0;
2018 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002019 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002020
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002021 j = mbedtls_mpi_bitlen( &A );
2022 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002023 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002024 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002025 }
2026
2027 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002028 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002029 }
2030
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002031 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2032 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002033
2034 /*
2035 * A = A^R mod |X|
2036 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002037 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002038
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002039 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2040 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002041 continue;
2042
2043 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002044 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002045 {
2046 /*
2047 * A = A * A mod |X|
2048 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2050 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002051
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002053 break;
2054
2055 j++;
2056 }
2057
2058 /*
2059 * not prime if A != |X| - 1 or A == 1
2060 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002061 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2062 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002063 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002064 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002065 break;
2066 }
2067 }
2068
2069cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002070 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2071 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002072
2073 return( ret );
2074}
2075
2076/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002077 * Pseudo-primality test: small factors, then Miller-Rabin
2078 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002079int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002080 int (*f_rng)(void *, unsigned char *, size_t),
2081 void *p_rng )
2082{
2083 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002084 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002085
2086 XX.s = 1;
2087 XX.n = X->n;
2088 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002089
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002090 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2091 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2092 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002093
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002094 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002095 return( 0 );
2096
2097 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2098 {
2099 if( ret == 1 )
2100 return( 0 );
2101
2102 return( ret );
2103 }
2104
2105 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2106}
2107
2108/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002109 * Prime number generation
2110 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002111int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002112 int (*f_rng)(void *, unsigned char *, size_t),
2113 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002114{
Paul Bakker23986e52011-04-24 08:57:21 +00002115 int ret;
2116 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002117 mbedtls_mpi_uint r;
2118 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002120 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2121 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002123 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002124
2125 n = BITS_TO_LIMBS( nbits );
2126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002127 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002128
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002129 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002130 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002131
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002132 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002133
2134 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002135
2136 if( dh_flag == 0 )
2137 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002138 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002139 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002140 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002141 goto cleanup;
2142
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002143 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002144 }
2145 }
2146 else
2147 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002148 /*
2149 * An necessary condition for Y and X = 2Y + 1 to be prime
2150 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2151 * Make sure it is satisfied, while keeping X = 3 mod 4
2152 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002153
2154 X->p[0] |= 2;
2155
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002156 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002157 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002158 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002159 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002161
2162 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002163 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2164 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002165
2166 while( 1 )
2167 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002168 /*
2169 * First, check small factors for X and Y
2170 * before doing Miller-Rabin on any of them
2171 */
2172 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2173 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2174 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2175 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002176 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002177 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002178 }
2179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002180 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002181 goto cleanup;
2182
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002183 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002184 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002185 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2186 * so up Y by 6 and X by 12.
2187 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2189 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002190 }
2191 }
2192
2193cleanup:
2194
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002195 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002196
2197 return( ret );
2198}
2199
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002200#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002202#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002203
Paul Bakker23986e52011-04-24 08:57:21 +00002204#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002205
2206static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2207{
2208 { 693, 609, 21 },
2209 { 1764, 868, 28 },
2210 { 768454923, 542167814, 1 }
2211};
2212
Paul Bakker5121ce52009-01-03 21:22:43 +00002213/*
2214 * Checkup routine
2215 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002216int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002217{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002218 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002219 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002220
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002221 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2222 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002223
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002224 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002225 "EFE021C2645FD1DC586E69184AF4A31E" \
2226 "D5F53E93B5F123FA41680867BA110131" \
2227 "944FE7952E2517337780CB0DB80E61AA" \
2228 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2229
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002230 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002231 "B2E7EFD37075B9F03FF989C7C5051C20" \
2232 "34D2A323810251127E7BF8625A4F49A5" \
2233 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2234 "5B5C25763222FEFCCFC38B832366C29E" ) );
2235
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002236 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002237 "0066A198186C18C10B2F5ED9B522752A" \
2238 "9830B69916E535C8F047518A889A43A5" \
2239 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002241 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002242
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002243 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002244 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2245 "9E857EA95A03512E2BAE7391688D264A" \
2246 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2247 "8001B72E848A38CAE1C65F78E56ABDEF" \
2248 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2249 "ECF677152EF804370C1A305CAF3B5BF1" \
2250 "30879B56C61DE584A0F53A2447A51E" ) );
2251
2252 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002253 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002254
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002255 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002256 {
2257 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002258 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002259
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002260 ret = 1;
2261 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002262 }
2263
2264 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002265 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002267 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002268
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002269 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002270 "256567336059E52CAE22925474705F39A94" ) );
2271
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002273 "6613F26162223DF488E9CD48CC132C7A" \
2274 "0AC93C701B001B092E4E5B9F73BCD27B" \
2275 "9EE50D0657C77F374E903CDFA4C642" ) );
2276
2277 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002278 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002279
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002280 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2281 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002282 {
2283 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002284 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002285
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002286 ret = 1;
2287 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002288 }
2289
2290 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002291 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002293 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002294
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002295 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002296 "36E139AEA55215609D2816998ED020BB" \
2297 "BD96C37890F65171D948E9BC7CBAA4D9" \
2298 "325D24D6A3C12710F10A09FA08AB87" ) );
2299
2300 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002301 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002302
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002303 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002304 {
2305 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002306 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002307
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002308 ret = 1;
2309 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002310 }
2311
2312 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002313 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002314
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002315 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002316
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002317 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002318 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2319 "C3DBA76456363A10869622EAC2DD84EC" \
2320 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2321
2322 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002323 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002324
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002325 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002326 {
2327 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002328 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002329
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002330 ret = 1;
2331 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002332 }
2333
2334 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002336
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002337 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002339
Paul Bakker66d5d072014-06-17 16:39:18 +02002340 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002341 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2343 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002345 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002346
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002348 {
2349 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002350 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002351
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002352 ret = 1;
2353 goto cleanup;
2354 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002355 }
2356
2357 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002358 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002359
Paul Bakker5121ce52009-01-03 21:22:43 +00002360cleanup:
2361
2362 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002363 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002364
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002365 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2366 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002367
2368 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002369 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002370
2371 return( ret );
2372}
2373
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002374#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002375
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376#endif /* MBEDTLS_BIGNUM_C */