blob: 1b80200cb17cdf7a8fe2e3a290b24367c95ca915 [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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020025 * http://www.stillhq.com/extracted/gnupg-api/mbedtls_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;
Paul Bakker5121ce52009-01-03 21:22:43 +0000862
863 if( X == B )
864 {
Janos Follath044a86b2015-10-25 10:58:03 +0100865 const mbedtls_mpi *T;
866
867 if( B == A)
868 return mbedtls_mpi_shift_l( X, 1 );
869
870 T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000871 }
872
873 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200874 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200875
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000876 /*
877 * X should always be positive as a result of unsigned additions.
878 */
879 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000880
Paul Bakker23986e52011-04-24 08:57:21 +0000881 for( j = B->n; j > 0; j-- )
882 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000883 break;
884
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200885 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000886
887 o = B->p; p = X->p; c = 0;
888
Paul Bakker23986e52011-04-24 08:57:21 +0000889 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000890 {
891 *p += c; c = ( *p < c );
892 *p += *o; c += ( *p < *o );
893 }
894
895 while( c != 0 )
896 {
897 if( i >= X->n )
898 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200899 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000900 p = X->p + i;
901 }
902
Paul Bakker2d319fd2012-09-16 21:34:26 +0000903 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000904 }
905
906cleanup:
907
908 return( ret );
909}
910
911/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200912 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000913 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200914static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000915{
Paul Bakker23986e52011-04-24 08:57:21 +0000916 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200917 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000918
919 for( i = c = 0; i < n; i++, s++, d++ )
920 {
921 z = ( *d < c ); *d -= c;
922 c = ( *d < *s ) + z; *d -= *s;
923 }
924
925 while( c != 0 )
926 {
927 z = ( *d < c ); *d -= c;
928 c = z; i++; d++;
929 }
930}
931
932/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100933 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000934 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200935int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000936{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200937 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000938 int ret;
939 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000940
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
942 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000943
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200944 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000945
946 if( X == B )
947 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200948 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000949 B = &TB;
950 }
951
952 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200953 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000954
Paul Bakker1ef7a532009-06-20 10:50:55 +0000955 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100956 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000957 */
958 X->s = 1;
959
Paul Bakker5121ce52009-01-03 21:22:43 +0000960 ret = 0;
961
Paul Bakker23986e52011-04-24 08:57:21 +0000962 for( n = B->n; n > 0; n-- )
963 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000964 break;
965
Paul Bakker23986e52011-04-24 08:57:21 +0000966 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000967
968cleanup:
969
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200970 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000971
972 return( ret );
973}
974
975/*
976 * Signed addition: X = A + B
977 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200978int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000979{
980 int ret, s = A->s;
981
982 if( A->s * B->s < 0 )
983 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200984 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000985 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200986 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000987 X->s = s;
988 }
989 else
990 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200991 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000992 X->s = -s;
993 }
994 }
995 else
996 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200997 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000998 X->s = s;
999 }
1000
1001cleanup:
1002
1003 return( ret );
1004}
1005
1006/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001007 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001008 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001009int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001010{
1011 int ret, s = A->s;
1012
1013 if( A->s * B->s > 0 )
1014 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001015 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001016 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001017 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001018 X->s = s;
1019 }
1020 else
1021 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001022 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001023 X->s = -s;
1024 }
1025 }
1026 else
1027 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001028 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001029 X->s = s;
1030 }
1031
1032cleanup:
1033
1034 return( ret );
1035}
1036
1037/*
1038 * Signed addition: X = A + b
1039 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001040int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001041{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042 mbedtls_mpi _B;
1043 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001044
1045 p[0] = ( b < 0 ) ? -b : b;
1046 _B.s = ( b < 0 ) ? -1 : 1;
1047 _B.n = 1;
1048 _B.p = p;
1049
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001051}
1052
1053/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001054 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001055 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001056int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001057{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001058 mbedtls_mpi _B;
1059 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001060
1061 p[0] = ( b < 0 ) ? -b : b;
1062 _B.s = ( b < 0 ) ? -1 : 1;
1063 _B.n = 1;
1064 _B.p = p;
1065
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001066 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001067}
1068
1069/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001070 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001071 */
1072static
1073#if defined(__APPLE__) && defined(__arm__)
1074/*
1075 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1076 * appears to need this to prevent bad ARM code generation at -O3.
1077 */
1078__attribute__ ((noinline))
1079#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001080void 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 +00001081{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001082 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001083
1084#if defined(MULADDC_HUIT)
1085 for( ; i >= 8; i -= 8 )
1086 {
1087 MULADDC_INIT
1088 MULADDC_HUIT
1089 MULADDC_STOP
1090 }
1091
1092 for( ; i > 0; i-- )
1093 {
1094 MULADDC_INIT
1095 MULADDC_CORE
1096 MULADDC_STOP
1097 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001098#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001099 for( ; i >= 16; i -= 16 )
1100 {
1101 MULADDC_INIT
1102 MULADDC_CORE MULADDC_CORE
1103 MULADDC_CORE MULADDC_CORE
1104 MULADDC_CORE MULADDC_CORE
1105 MULADDC_CORE MULADDC_CORE
1106
1107 MULADDC_CORE MULADDC_CORE
1108 MULADDC_CORE MULADDC_CORE
1109 MULADDC_CORE MULADDC_CORE
1110 MULADDC_CORE MULADDC_CORE
1111 MULADDC_STOP
1112 }
1113
1114 for( ; i >= 8; i -= 8 )
1115 {
1116 MULADDC_INIT
1117 MULADDC_CORE MULADDC_CORE
1118 MULADDC_CORE MULADDC_CORE
1119
1120 MULADDC_CORE MULADDC_CORE
1121 MULADDC_CORE MULADDC_CORE
1122 MULADDC_STOP
1123 }
1124
1125 for( ; i > 0; i-- )
1126 {
1127 MULADDC_INIT
1128 MULADDC_CORE
1129 MULADDC_STOP
1130 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001131#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001132
1133 t++;
1134
1135 do {
1136 *d += c; c = ( *d < c ); d++;
1137 }
1138 while( c != 0 );
1139}
1140
1141/*
1142 * Baseline multiplication: X = A * B (HAC 14.12)
1143 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001144int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001145{
Paul Bakker23986e52011-04-24 08:57:21 +00001146 int ret;
1147 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001148 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001149
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001150 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001152 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1153 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001154
Paul Bakker23986e52011-04-24 08:57:21 +00001155 for( i = A->n; i > 0; i-- )
1156 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001157 break;
1158
Paul Bakker23986e52011-04-24 08:57:21 +00001159 for( j = B->n; j > 0; j-- )
1160 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001161 break;
1162
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001163 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1164 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001165
Paul Bakker23986e52011-04-24 08:57:21 +00001166 for( i++; j > 0; j-- )
1167 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001168
1169 X->s = A->s * B->s;
1170
1171cleanup:
1172
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001173 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001174
1175 return( ret );
1176}
1177
1178/*
1179 * Baseline multiplication: X = A * b
1180 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001181int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001182{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001183 mbedtls_mpi _B;
1184 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001185
1186 _B.s = 1;
1187 _B.n = 1;
1188 _B.p = p;
1189 p[0] = b;
1190
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001191 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001192}
1193
1194/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001195 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001196 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001197int 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 +00001198{
Paul Bakker23986e52011-04-24 08:57:21 +00001199 int ret;
1200 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001201 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001202
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001203 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1204 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001205
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001206 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1207 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001209 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001210 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001211 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1212 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001213 return( 0 );
1214 }
1215
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001216 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1217 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001218 X.s = Y.s = 1;
1219
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001220 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1221 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1222 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1223 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001224
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001225 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001226 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001227 {
1228 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001229 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1230 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001231 }
1232 else k = 0;
1233
1234 n = X.n - 1;
1235 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001236 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001237
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001238 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001239 {
1240 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001241 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001242 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001243 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001244
1245 for( i = n; i > t ; i-- )
1246 {
1247 if( X.p[i] >= Y.p[t] )
1248 Z.p[i - t - 1] = ~0;
1249 else
1250 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001251#if defined(MBEDTLS_HAVE_UDBL)
1252 mbedtls_t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001253
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001254 r = (mbedtls_t_udbl) X.p[i] << biL;
1255 r |= (mbedtls_t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001256 r /= Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001257 if( r > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1258 r = ( (mbedtls_t_udbl) 1 << biL ) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001259
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001260 Z.p[i - t - 1] = (mbedtls_mpi_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001261#else
1262 /*
1263 * __udiv_qrnnd_c, from gmp/longlong.h
1264 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001265 mbedtls_mpi_uint q0, q1, r0, r1;
1266 mbedtls_mpi_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001267
1268 d = Y.p[t];
1269 d0 = ( d << biH ) >> biH;
1270 d1 = ( d >> biH );
1271
1272 q1 = X.p[i] / d1;
1273 r1 = X.p[i] - d1 * q1;
1274 r1 <<= biH;
1275 r1 |= ( X.p[i - 1] >> biH );
1276
1277 m = q1 * d0;
1278 if( r1 < m )
1279 {
1280 q1--, r1 += d;
1281 while( r1 >= d && r1 < m )
1282 q1--, r1 += d;
1283 }
1284 r1 -= m;
1285
1286 q0 = r1 / d1;
1287 r0 = r1 - d1 * q0;
1288 r0 <<= biH;
1289 r0 |= ( X.p[i - 1] << biH ) >> biH;
1290
1291 m = q0 * d0;
1292 if( r0 < m )
1293 {
1294 q0--, r0 += d;
1295 while( r0 >= d && r0 < m )
1296 q0--, r0 += d;
1297 }
1298 r0 -= m;
1299
1300 Z.p[i - t - 1] = ( q1 << biH ) | q0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001301#endif /* MBEDTLS_HAVE_UDBL && !64-bit Apple with Clang 5.0 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001302 }
1303
1304 Z.p[i - t - 1]++;
1305 do
1306 {
1307 Z.p[i - t - 1]--;
1308
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001309 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001310 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001311 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001312 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001313
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001314 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001315 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1316 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001317 T2.p[2] = X.p[i];
1318 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001319 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001321 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1322 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1323 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001324
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001325 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001326 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001327 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1328 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1329 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001330 Z.p[i - t - 1]--;
1331 }
1332 }
1333
1334 if( Q != NULL )
1335 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001337 Q->s = A->s * B->s;
1338 }
1339
1340 if( R != NULL )
1341 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001342 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001343 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001344 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001346 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001347 R->s = 1;
1348 }
1349
1350cleanup:
1351
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001352 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1353 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001354
1355 return( ret );
1356}
1357
1358/*
1359 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001360 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001361int 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 +00001362{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001363 mbedtls_mpi _B;
1364 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001365
1366 p[0] = ( b < 0 ) ? -b : b;
1367 _B.s = ( b < 0 ) ? -1 : 1;
1368 _B.n = 1;
1369 _B.p = p;
1370
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001371 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001372}
1373
1374/*
1375 * Modulo: R = A mod B
1376 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001377int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001378{
1379 int ret;
1380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001381 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1382 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001383
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001384 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001385
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001386 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1387 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001389 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1390 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001391
1392cleanup:
1393
1394 return( ret );
1395}
1396
1397/*
1398 * Modulo: r = A mod b
1399 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001401{
Paul Bakker23986e52011-04-24 08:57:21 +00001402 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001404
1405 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001407
1408 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001409 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001410
1411 /*
1412 * handle trivial cases
1413 */
1414 if( b == 1 )
1415 {
1416 *r = 0;
1417 return( 0 );
1418 }
1419
1420 if( b == 2 )
1421 {
1422 *r = A->p[0] & 1;
1423 return( 0 );
1424 }
1425
1426 /*
1427 * general case
1428 */
Paul Bakker23986e52011-04-24 08:57:21 +00001429 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001430 {
Paul Bakker23986e52011-04-24 08:57:21 +00001431 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001432 y = ( y << biH ) | ( x >> biH );
1433 z = y / b;
1434 y -= z * b;
1435
1436 x <<= biH;
1437 y = ( y << biH ) | ( x >> biH );
1438 z = y / b;
1439 y -= z * b;
1440 }
1441
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001442 /*
1443 * If A is negative, then the current y represents a negative value.
1444 * Flipping it to the positive side.
1445 */
1446 if( A->s < 0 && y != 0 )
1447 y = b - y;
1448
Paul Bakker5121ce52009-01-03 21:22:43 +00001449 *r = y;
1450
1451 return( 0 );
1452}
1453
1454/*
1455 * Fast Montgomery initialization (thanks to Tom St Denis)
1456 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001457static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001458{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001459 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001460 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001461
1462 x = m0;
1463 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001464
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001465 for( i = biL; i >= 8; i /= 2 )
1466 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001467
1468 *mm = ~x + 1;
1469}
1470
1471/*
1472 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1473 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001474static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1475 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001476{
Paul Bakker23986e52011-04-24 08:57:21 +00001477 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001478 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001479
1480 memset( T->p, 0, T->n * ciL );
1481
1482 d = T->p;
1483 n = N->n;
1484 m = ( B->n < n ) ? B->n : n;
1485
1486 for( i = 0; i < n; i++ )
1487 {
1488 /*
1489 * T = (T + u0*B + u1*N) / 2^biL
1490 */
1491 u0 = A->p[i];
1492 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1493
1494 mpi_mul_hlp( m, B->p, d, u0 );
1495 mpi_mul_hlp( n, N->p, d, u1 );
1496
1497 *d++ = u0; d[n + 1] = 0;
1498 }
1499
Paul Bakker66d5d072014-06-17 16:39:18 +02001500 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001501
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001502 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001503 mpi_sub_hlp( n, N->p, A->p );
1504 else
1505 /* prevent timing attacks */
1506 mpi_sub_hlp( n, A->p, T->p );
1507}
1508
1509/*
1510 * Montgomery reduction: A = A * R^-1 mod N
1511 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001512static 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 +00001513{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001514 mbedtls_mpi_uint z = 1;
1515 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001516
Paul Bakker8ddb6452013-02-27 14:56:33 +01001517 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001518 U.p = &z;
1519
1520 mpi_montmul( A, &U, N, mm, T );
1521}
1522
1523/*
1524 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1525 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001526int 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 +00001527{
Paul Bakker23986e52011-04-24 08:57:21 +00001528 int ret;
1529 size_t wbits, wsize, one = 1;
1530 size_t i, j, nblimbs;
1531 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001532 mbedtls_mpi_uint ei, mm, state;
1533 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001534 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001535
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001536 if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
1537 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001538
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1540 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001541
1542 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001543 * Init temps and window size
1544 */
1545 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001546 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1547 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001548 memset( W, 0, sizeof( W ) );
1549
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001550 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001551
1552 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1553 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001555 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1556 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001557
Paul Bakker5121ce52009-01-03 21:22:43 +00001558 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001559 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1560 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1561 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001562
1563 /*
Paul Bakker50546922012-05-19 08:40:49 +00001564 * Compensate for negative A (and correct at the end)
1565 */
1566 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001567 if( neg )
1568 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001569 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001570 Apos.s = 1;
1571 A = &Apos;
1572 }
1573
1574 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001575 * If 1st call, pre-compute R^2 mod N
1576 */
1577 if( _RR == NULL || _RR->p == NULL )
1578 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001579 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1580 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1581 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001582
1583 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001584 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001585 }
1586 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001587 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001588
1589 /*
1590 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1591 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001592 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1593 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001594 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001595 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001596
1597 mpi_montmul( &W[1], &RR, N, mm, &T );
1598
1599 /*
1600 * X = R^2 * R^-1 mod N = R mod N
1601 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001602 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001603 mpi_montred( X, N, mm, &T );
1604
1605 if( wsize > 1 )
1606 {
1607 /*
1608 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1609 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001610 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001612 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1613 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001614
1615 for( i = 0; i < wsize - 1; i++ )
1616 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001617
Paul Bakker5121ce52009-01-03 21:22:43 +00001618 /*
1619 * W[i] = W[i - 1] * W[1]
1620 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001621 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001622 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001623 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1624 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001625
1626 mpi_montmul( &W[i], &W[1], N, mm, &T );
1627 }
1628 }
1629
1630 nblimbs = E->n;
1631 bufsize = 0;
1632 nbits = 0;
1633 wbits = 0;
1634 state = 0;
1635
1636 while( 1 )
1637 {
1638 if( bufsize == 0 )
1639 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001640 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001641 break;
1642
Paul Bakker0d7702c2013-10-29 16:18:35 +01001643 nblimbs--;
1644
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001645 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001646 }
1647
1648 bufsize--;
1649
1650 ei = (E->p[nblimbs] >> bufsize) & 1;
1651
1652 /*
1653 * skip leading 0s
1654 */
1655 if( ei == 0 && state == 0 )
1656 continue;
1657
1658 if( ei == 0 && state == 1 )
1659 {
1660 /*
1661 * out of window, square X
1662 */
1663 mpi_montmul( X, X, N, mm, &T );
1664 continue;
1665 }
1666
1667 /*
1668 * add ei to current window
1669 */
1670 state = 2;
1671
1672 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001673 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001674
1675 if( nbits == wsize )
1676 {
1677 /*
1678 * X = X^wsize R^-1 mod N
1679 */
1680 for( i = 0; i < wsize; i++ )
1681 mpi_montmul( X, X, N, mm, &T );
1682
1683 /*
1684 * X = X * W[wbits] R^-1 mod N
1685 */
1686 mpi_montmul( X, &W[wbits], N, mm, &T );
1687
1688 state--;
1689 nbits = 0;
1690 wbits = 0;
1691 }
1692 }
1693
1694 /*
1695 * process the remaining bits
1696 */
1697 for( i = 0; i < nbits; i++ )
1698 {
1699 mpi_montmul( X, X, N, mm, &T );
1700
1701 wbits <<= 1;
1702
Paul Bakker66d5d072014-06-17 16:39:18 +02001703 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001704 mpi_montmul( X, &W[1], N, mm, &T );
1705 }
1706
1707 /*
1708 * X = A^E * R * R^-1 mod N = A^E mod N
1709 */
1710 mpi_montred( X, N, mm, &T );
1711
Paul Bakkerf6198c12012-05-16 08:02:29 +00001712 if( neg )
1713 {
1714 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001715 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001716 }
1717
Paul Bakker5121ce52009-01-03 21:22:43 +00001718cleanup:
1719
Paul Bakker66d5d072014-06-17 16:39:18 +02001720 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001721 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001722
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001723 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001724
Paul Bakker75a28602014-03-31 12:08:17 +02001725 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001726 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001727
1728 return( ret );
1729}
1730
Paul Bakker5121ce52009-01-03 21:22:43 +00001731/*
1732 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1733 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001734int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001735{
Paul Bakker23986e52011-04-24 08:57:21 +00001736 int ret;
1737 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001738 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001739
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001740 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001741
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001742 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1743 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001744
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001745 lz = mbedtls_mpi_lsb( &TA );
1746 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001747
Paul Bakker66d5d072014-06-17 16:39:18 +02001748 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001749 lz = lzt;
1750
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001751 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1752 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001753
Paul Bakker5121ce52009-01-03 21:22:43 +00001754 TA.s = TB.s = 1;
1755
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001756 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001757 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001758 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1759 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001760
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001761 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001762 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001763 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1764 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001765 }
1766 else
1767 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001768 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1769 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001770 }
1771 }
1772
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001773 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1774 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001775
1776cleanup:
1777
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001778 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001779
1780 return( ret );
1781}
1782
Paul Bakker33dc46b2014-04-30 16:11:39 +02001783/*
1784 * Fill X with size bytes of random.
1785 *
1786 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001787 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001788 * deterministic, eg for tests).
1789 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001790int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001791 int (*f_rng)(void *, unsigned char *, size_t),
1792 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001793{
Paul Bakker23986e52011-04-24 08:57:21 +00001794 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001795 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001796
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001797 if( size > MBEDTLS_MPI_MAX_SIZE )
1798 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001799
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001800 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1801 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001802
1803cleanup:
1804 return( ret );
1805}
1806
Paul Bakker5121ce52009-01-03 21:22:43 +00001807/*
1808 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1809 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001810int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001811{
1812 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001813 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001814
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001815 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 )
1816 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001817
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001818 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1819 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1820 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001821
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001822 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001823
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001825 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001826 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001827 goto cleanup;
1828 }
1829
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1831 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1832 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1833 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001834
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001835 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1836 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1837 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1838 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001839
1840 do
1841 {
1842 while( ( TU.p[0] & 1 ) == 0 )
1843 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001845
1846 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1847 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001848 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1849 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001850 }
1851
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001852 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1853 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001854 }
1855
1856 while( ( TV.p[0] & 1 ) == 0 )
1857 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001858 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001859
1860 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1861 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001862 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1863 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001864 }
1865
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001866 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1867 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001868 }
1869
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001870 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001871 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001872 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1873 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1874 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001875 }
1876 else
1877 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001878 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1879 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1880 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001881 }
1882 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001883 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001884
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001885 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1886 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001887
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001888 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1889 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001890
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001891 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001892
1893cleanup:
1894
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001895 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1896 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1897 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001898
1899 return( ret );
1900}
1901
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001902#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001903
Paul Bakker5121ce52009-01-03 21:22:43 +00001904static const int small_prime[] =
1905{
1906 3, 5, 7, 11, 13, 17, 19, 23,
1907 29, 31, 37, 41, 43, 47, 53, 59,
1908 61, 67, 71, 73, 79, 83, 89, 97,
1909 101, 103, 107, 109, 113, 127, 131, 137,
1910 139, 149, 151, 157, 163, 167, 173, 179,
1911 181, 191, 193, 197, 199, 211, 223, 227,
1912 229, 233, 239, 241, 251, 257, 263, 269,
1913 271, 277, 281, 283, 293, 307, 311, 313,
1914 317, 331, 337, 347, 349, 353, 359, 367,
1915 373, 379, 383, 389, 397, 401, 409, 419,
1916 421, 431, 433, 439, 443, 449, 457, 461,
1917 463, 467, 479, 487, 491, 499, 503, 509,
1918 521, 523, 541, 547, 557, 563, 569, 571,
1919 577, 587, 593, 599, 601, 607, 613, 617,
1920 619, 631, 641, 643, 647, 653, 659, 661,
1921 673, 677, 683, 691, 701, 709, 719, 727,
1922 733, 739, 743, 751, 757, 761, 769, 773,
1923 787, 797, 809, 811, 821, 823, 827, 829,
1924 839, 853, 857, 859, 863, 877, 881, 883,
1925 887, 907, 911, 919, 929, 937, 941, 947,
1926 953, 967, 971, 977, 983, 991, 997, -103
1927};
1928
1929/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001930 * Small divisors test (X must be positive)
1931 *
1932 * Return values:
1933 * 0: no small factor (possible prime, more tests needed)
1934 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001935 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001936 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00001937 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001938static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00001939{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001940 int ret = 0;
1941 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001942 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001943
Paul Bakker5121ce52009-01-03 21:22:43 +00001944 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001945 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001946
1947 for( i = 0; small_prime[i] > 0; i++ )
1948 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001949 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001950 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001951
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001952 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001953
1954 if( r == 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
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001958cleanup:
1959 return( ret );
1960}
1961
1962/*
1963 * Miller-Rabin pseudo-primality test (HAC 4.24)
1964 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001965static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001966 int (*f_rng)(void *, unsigned char *, size_t),
1967 void *p_rng )
1968{
Pascal Junodb99183d2015-03-11 16:49:45 +01001969 int ret, count;
1970 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001971 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001972
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001973 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
1974 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001975
Paul Bakker5121ce52009-01-03 21:22:43 +00001976 /*
1977 * W = |X| - 1
1978 * R = W >> lsb( W )
1979 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001980 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
1981 s = mbedtls_mpi_lsb( &W );
1982 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
1983 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001984
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001985 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00001986 /*
1987 * HAC, table 4.4
1988 */
1989 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1990 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1991 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1992
1993 for( i = 0; i < n; i++ )
1994 {
1995 /*
1996 * pick a random A, 1 < A < |X| - 1
1997 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001998 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001999
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002000 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00002001 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002002 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002003 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00002004 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002005 A.p[0] |= 3;
2006
Pascal Junodb99183d2015-03-11 16:49:45 +01002007 count = 0;
2008 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002009 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002010
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002011 j = mbedtls_mpi_bitlen( &A );
2012 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002013 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002014 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002015 }
2016
2017 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002018 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002019 }
2020
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002021 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2022 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002023
2024 /*
2025 * A = A^R mod |X|
2026 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002027 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002028
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2030 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002031 continue;
2032
2033 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002035 {
2036 /*
2037 * A = A * A mod |X|
2038 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002039 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2040 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002041
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002042 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002043 break;
2044
2045 j++;
2046 }
2047
2048 /*
2049 * not prime if A != |X| - 1 or A == 1
2050 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002051 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2052 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002053 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002054 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002055 break;
2056 }
2057 }
2058
2059cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2061 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002062
2063 return( ret );
2064}
2065
2066/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002067 * Pseudo-primality test: small factors, then Miller-Rabin
2068 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002069int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002070 int (*f_rng)(void *, unsigned char *, size_t),
2071 void *p_rng )
2072{
2073 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002074 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002075
2076 XX.s = 1;
2077 XX.n = X->n;
2078 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002079
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002080 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2081 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2082 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002083
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002084 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002085 return( 0 );
2086
2087 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2088 {
2089 if( ret == 1 )
2090 return( 0 );
2091
2092 return( ret );
2093 }
2094
2095 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2096}
2097
2098/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002099 * Prime number generation
2100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002101int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002102 int (*f_rng)(void *, unsigned char *, size_t),
2103 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002104{
Paul Bakker23986e52011-04-24 08:57:21 +00002105 int ret;
2106 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002107 mbedtls_mpi_uint r;
2108 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002110 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2111 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002113 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002114
2115 n = BITS_TO_LIMBS( nbits );
2116
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002117 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002118
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002119 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002120 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002121
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002122 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002123
2124 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002125
2126 if( dh_flag == 0 )
2127 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002128 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002129 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002130 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002131 goto cleanup;
2132
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002133 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002134 }
2135 }
2136 else
2137 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002138 /*
2139 * An necessary condition for Y and X = 2Y + 1 to be prime
2140 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2141 * Make sure it is satisfied, while keeping X = 3 mod 4
2142 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002143
2144 X->p[0] |= 2;
2145
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002146 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002147 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002148 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002149 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002150 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002151
2152 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002153 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2154 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002155
2156 while( 1 )
2157 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002158 /*
2159 * First, check small factors for X and Y
2160 * before doing Miller-Rabin on any of them
2161 */
2162 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2163 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2164 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2165 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002166 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002167 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002168 }
2169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002170 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002171 goto cleanup;
2172
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002173 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002174 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002175 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2176 * so up Y by 6 and X by 12.
2177 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002178 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2179 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002180 }
2181 }
2182
2183cleanup:
2184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002185 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002186
2187 return( ret );
2188}
2189
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002190#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002192#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002193
Paul Bakker23986e52011-04-24 08:57:21 +00002194#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002195
2196static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2197{
2198 { 693, 609, 21 },
2199 { 1764, 868, 28 },
2200 { 768454923, 542167814, 1 }
2201};
2202
Paul Bakker5121ce52009-01-03 21:22:43 +00002203/*
2204 * Checkup routine
2205 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002207{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002208 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002209 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002210
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002211 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2212 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002213
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002214 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002215 "EFE021C2645FD1DC586E69184AF4A31E" \
2216 "D5F53E93B5F123FA41680867BA110131" \
2217 "944FE7952E2517337780CB0DB80E61AA" \
2218 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2219
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002220 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002221 "B2E7EFD37075B9F03FF989C7C5051C20" \
2222 "34D2A323810251127E7BF8625A4F49A5" \
2223 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2224 "5B5C25763222FEFCCFC38B832366C29E" ) );
2225
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002226 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002227 "0066A198186C18C10B2F5ED9B522752A" \
2228 "9830B69916E535C8F047518A889A43A5" \
2229 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2230
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002231 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002232
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002233 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002234 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2235 "9E857EA95A03512E2BAE7391688D264A" \
2236 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2237 "8001B72E848A38CAE1C65F78E56ABDEF" \
2238 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2239 "ECF677152EF804370C1A305CAF3B5BF1" \
2240 "30879B56C61DE584A0F53A2447A51E" ) );
2241
2242 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002243 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002244
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002245 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002246 {
2247 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002248 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002249
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002250 ret = 1;
2251 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002252 }
2253
2254 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002255 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002256
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002257 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002259 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002260 "256567336059E52CAE22925474705F39A94" ) );
2261
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002262 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002263 "6613F26162223DF488E9CD48CC132C7A" \
2264 "0AC93C701B001B092E4E5B9F73BCD27B" \
2265 "9EE50D0657C77F374E903CDFA4C642" ) );
2266
2267 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002268 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002269
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002270 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2271 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002272 {
2273 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002274 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002275
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002276 ret = 1;
2277 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002278 }
2279
2280 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002281 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002283 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002284
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002285 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002286 "36E139AEA55215609D2816998ED020BB" \
2287 "BD96C37890F65171D948E9BC7CBAA4D9" \
2288 "325D24D6A3C12710F10A09FA08AB87" ) );
2289
2290 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002291 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002293 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002294 {
2295 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002296 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002297
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002298 ret = 1;
2299 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002300 }
2301
2302 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002303 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002304
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002305 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002308 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2309 "C3DBA76456363A10869622EAC2DD84EC" \
2310 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2311
2312 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002313 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002314
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002315 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002316 {
2317 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002318 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002319
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002320 ret = 1;
2321 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002322 }
2323
2324 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002325 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002326
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002327 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002328 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002329
Paul Bakker66d5d072014-06-17 16:39:18 +02002330 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002331 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002332 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2333 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002336
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002337 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002338 {
2339 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002340 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002341
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002342 ret = 1;
2343 goto cleanup;
2344 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002345 }
2346
2347 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002348 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002349
Paul Bakker5121ce52009-01-03 21:22:43 +00002350cleanup:
2351
2352 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002354
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002355 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2356 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002357
2358 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
2361 return( ret );
2362}
2363
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002364#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002366#endif /* MBEDTLS_BIGNUM_C */