blob: b587b6761eeba7da883a5ea6a730e453a3d7b678 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
21/*
22 * This MPI implementation is based on:
23 *
24 * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
Simon Butcher334a87b2015-10-14 22:56:44 +010025 * http://www.stillhq.com/extracted/gnupg-api/mpi/
Paul Bakker5121ce52009-01-03 21:22:43 +000026 * http://math.libtomcrypt.com/files/tommath.pdf
27 */
28
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020029#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000030#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020031#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020033#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000034
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000036
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000037#include "mbedtls/bignum.h"
38#include "mbedtls/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000039
Rich Evans00ab4702015-02-06 13:43:58 +000040#include <string.h>
41
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020042#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000043#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020044#else
Rich Evans00ab4702015-02-06 13:43:58 +000045#include <stdio.h>
46#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020047#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020048#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020050#endif
51
Paul Bakker34617722014-06-13 17:20:13 +020052/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020053static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020054 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
55}
56
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000058#define biL (ciL << 3) /* bits in limb */
59#define biH (ciL << 2) /* half limb size */
60
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010061#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
62
Paul Bakker5121ce52009-01-03 21:22:43 +000063/*
64 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020065 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000066 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020067#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
68#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000069
70/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000071 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000072 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020073void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000074{
Paul Bakker6c591fa2011-05-05 11:49:20 +000075 if( X == NULL )
76 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000077
Paul Bakker6c591fa2011-05-05 11:49:20 +000078 X->s = 1;
79 X->n = 0;
80 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000081}
82
83/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000084 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000085 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020086void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000087{
Paul Bakker6c591fa2011-05-05 11:49:20 +000088 if( X == NULL )
89 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000090
Paul Bakker6c591fa2011-05-05 11:49:20 +000091 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +000092 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020093 mbedtls_zeroize( X->p, X->n * ciL );
94 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +000095 }
96
Paul Bakker6c591fa2011-05-05 11:49:20 +000097 X->s = 1;
98 X->n = 0;
99 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000100}
101
102/*
103 * Enlarge to the specified number of limbs
104 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200105int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000106{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200107 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000108
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200110 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000111
Paul Bakker5121ce52009-01-03 21:22:43 +0000112 if( X->n < nblimbs )
113 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200114 if( ( p = mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200115 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000116
Paul Bakker5121ce52009-01-03 21:22:43 +0000117 if( X->p != NULL )
118 {
119 memcpy( p, X->p, X->n * ciL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120 mbedtls_zeroize( X->p, X->n * ciL );
121 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000122 }
123
124 X->n = nblimbs;
125 X->p = p;
126 }
127
128 return( 0 );
129}
130
131/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100132 * Resize down as much as possible,
133 * while keeping at least the specified number of limbs
134 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100136{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100138 size_t i;
139
140 /* Actually resize up in this case */
141 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200142 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100143
144 for( i = X->n - 1; i > 0; i-- )
145 if( X->p[i] != 0 )
146 break;
147 i++;
148
149 if( i < nblimbs )
150 i = nblimbs;
151
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200152 if( ( p = mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200153 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100155 if( X->p != NULL )
156 {
157 memcpy( p, X->p, i * ciL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 mbedtls_zeroize( X->p, X->n * ciL );
159 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100160 }
161
162 X->n = i;
163 X->p = p;
164
165 return( 0 );
166}
167
168/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000169 * Copy the contents of Y into X
170 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000172{
Paul Bakker23986e52011-04-24 08:57:21 +0000173 int ret;
174 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000175
176 if( X == Y )
177 return( 0 );
178
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200179 if( Y->p == NULL )
180 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200182 return( 0 );
183 }
184
Paul Bakker5121ce52009-01-03 21:22:43 +0000185 for( i = Y->n - 1; i > 0; i-- )
186 if( Y->p[i] != 0 )
187 break;
188 i++;
189
190 X->s = Y->s;
191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200192 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000193
194 memset( X->p, 0, X->n * ciL );
195 memcpy( X->p, Y->p, i * ciL );
196
197cleanup:
198
199 return( ret );
200}
201
202/*
203 * Swap the contents of X and Y
204 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000206{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209 memcpy( &T, X, sizeof( mbedtls_mpi ) );
210 memcpy( X, Y, sizeof( mbedtls_mpi ) );
211 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000212}
213
214/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100215 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100216 * about whether the assignment was made or not.
217 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100218 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100220{
221 int ret = 0;
222 size_t i;
223
Pascal Junodb99183d2015-03-11 16:49:45 +0100224 /* make sure assign is 0 or 1 in a time-constant manner */
225 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200227 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100228
Paul Bakker66d5d072014-06-17 16:39:18 +0200229 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100230
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100231 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200232 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100233
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100234 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200235 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100236
237cleanup:
238 return( ret );
239}
240
241/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100242 * Conditionally swap X and Y, without leaking information
243 * about whether the swap was made or not.
244 * Here it is not ok to simply swap the pointers, which whould lead to
245 * different memory access patterns when X and Y are used afterwards.
246 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100248{
249 int ret, s;
250 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200251 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100252
253 if( X == Y )
254 return( 0 );
255
Pascal Junodb99183d2015-03-11 16:49:45 +0100256 /* make sure swap is 0 or 1 in a time-constant manner */
257 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
260 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100261
262 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200263 X->s = X->s * ( 1 - swap ) + Y->s * swap;
264 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100265
266
267 for( i = 0; i < X->n; i++ )
268 {
269 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200270 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
271 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100272 }
273
274cleanup:
275 return( ret );
276}
277
278/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000279 * Set value from integer
280 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000282{
283 int ret;
284
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200285 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000286 memset( X->p, 0, X->n * ciL );
287
288 X->p[0] = ( z < 0 ) ? -z : z;
289 X->s = ( z < 0 ) ? -1 : 1;
290
291cleanup:
292
293 return( ret );
294}
295
296/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000297 * Get a specific bit
298 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000300{
301 if( X->n * biL <= pos )
302 return( 0 );
303
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200304 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000305}
306
307/*
308 * Set a bit to a specific value of 0 or 1
309 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200310int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000311{
312 int ret = 0;
313 size_t off = pos / biL;
314 size_t idx = pos % biL;
315
316 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200317 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200318
Paul Bakker2f5947e2011-05-18 15:47:11 +0000319 if( X->n * biL <= pos )
320 {
321 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200322 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200324 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000325 }
326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
328 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000329
330cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200331
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332 return( ret );
333}
334
335/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200336 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000337 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200338size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000339{
Paul Bakker23986e52011-04-24 08:57:21 +0000340 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000341
342 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000343 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000344 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
345 return( count );
346
347 return( 0 );
348}
349
350/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200351 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000352 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200353size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000354{
Paul Bakker23986e52011-04-24 08:57:21 +0000355 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000356
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200357 if( X->n == 0 )
358 return( 0 );
359
Paul Bakker5121ce52009-01-03 21:22:43 +0000360 for( i = X->n - 1; i > 0; i-- )
361 if( X->p[i] != 0 )
362 break;
363
Paul Bakker23986e52011-04-24 08:57:21 +0000364 for( j = biL; j > 0; j-- )
365 if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000366 break;
367
Paul Bakker23986e52011-04-24 08:57:21 +0000368 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000369}
370
371/*
372 * Return the total size in bytes
373 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200374size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000375{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200376 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000377}
378
379/*
380 * Convert an ASCII character to digit value
381 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000383{
384 *d = 255;
385
386 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
387 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
388 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200390 if( *d >= (mbedtls_mpi_uint) radix )
391 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000392
393 return( 0 );
394}
395
396/*
397 * Import from an ASCII string
398 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000400{
Paul Bakker23986e52011-04-24 08:57:21 +0000401 int ret;
402 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200403 mbedtls_mpi_uint d;
404 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000405
406 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000410
Paul Bakkerff60ee62010-03-16 21:09:09 +0000411 slen = strlen( s );
412
Paul Bakker5121ce52009-01-03 21:22:43 +0000413 if( radix == 16 )
414 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100415 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200416 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
417
Paul Bakkerff60ee62010-03-16 21:09:09 +0000418 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000419
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200420 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
421 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000422
Paul Bakker23986e52011-04-24 08:57:21 +0000423 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000424 {
Paul Bakker23986e52011-04-24 08:57:21 +0000425 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000426 {
427 X->s = -1;
428 break;
429 }
430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200431 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200432 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000433 }
434 }
435 else
436 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000438
Paul Bakkerff60ee62010-03-16 21:09:09 +0000439 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000440 {
441 if( i == 0 && s[i] == '-' )
442 {
443 X->s = -1;
444 continue;
445 }
446
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200447 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
448 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000449
450 if( X->s == 1 )
451 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000453 }
454 else
455 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000457 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 }
459 }
460
461cleanup:
462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000464
465 return( ret );
466}
467
468/*
469 * Helper to write the digits high-order first
470 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000472{
473 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000475
476 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000478
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
480 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
483 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000484
485 if( r < 10 )
486 *(*p)++ = (char)( r + 0x30 );
487 else
488 *(*p)++ = (char)( r + 0x37 );
489
490cleanup:
491
492 return( ret );
493}
494
495/*
496 * Export into an ASCII string
497 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100498int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
499 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000500{
Paul Bakker23986e52011-04-24 08:57:21 +0000501 int ret = 0;
502 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000503 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000505
506 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000508
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200509 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000510 if( radix >= 4 ) n >>= 1;
511 if( radix >= 16 ) n >>= 1;
512 n += 3;
513
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100514 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000515 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100516 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000518 }
519
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100520 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000522
523 if( X->s == -1 )
524 *p++ = '-';
525
526 if( radix == 16 )
527 {
Paul Bakker23986e52011-04-24 08:57:21 +0000528 int c;
529 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000530
Paul Bakker23986e52011-04-24 08:57:21 +0000531 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000532 {
Paul Bakker23986e52011-04-24 08:57:21 +0000533 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000534 {
Paul Bakker23986e52011-04-24 08:57:21 +0000535 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000536
Paul Bakker6c343d72014-07-10 14:36:19 +0200537 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000538 continue;
539
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000540 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000541 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000542 k = 1;
543 }
544 }
545 }
546 else
547 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200548 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000549
550 if( T.s == -1 )
551 T.s = 1;
552
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000554 }
555
556 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100557 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000558
559cleanup:
560
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200561 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000562
563 return( ret );
564}
565
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000567/*
568 * Read X from an opened file
569 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200570int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000571{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200572 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000573 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000574 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000575 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000576 * Buffer should have space for (short) label and decimal formatted MPI,
577 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000578 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200579 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000580
581 memset( s, 0, sizeof( s ) );
582 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200583 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
585 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000586 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200587 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000588
Paul Bakker5121ce52009-01-03 21:22:43 +0000589 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
590 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
591
592 p = s + slen;
593 while( --p >= s )
594 if( mpi_get_digit( &d, radix, *p ) != 0 )
595 break;
596
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000598}
599
600/*
601 * Write X into an opened file (or stdout if fout == NULL)
602 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000604{
Paul Bakker23986e52011-04-24 08:57:21 +0000605 int ret;
606 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000607 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000608 * Buffer should have space for (short) label and decimal formatted MPI,
609 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000610 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000612
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100613 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000614
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100615 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000616
617 if( p == NULL ) p = "";
618
619 plen = strlen( p );
620 slen = strlen( s );
621 s[slen++] = '\r';
622 s[slen++] = '\n';
623
624 if( fout != NULL )
625 {
626 if( fwrite( p, 1, plen, fout ) != plen ||
627 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000629 }
630 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000632
633cleanup:
634
635 return( ret );
636}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000638
639/*
640 * Import X from unsigned binary data, big endian
641 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000643{
Paul Bakker23986e52011-04-24 08:57:21 +0000644 int ret;
645 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000646
647 for( n = 0; n < buflen; n++ )
648 if( buf[n] != 0 )
649 break;
650
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
652 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000653
Paul Bakker23986e52011-04-24 08:57:21 +0000654 for( i = buflen, j = 0; i > n; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000656
657cleanup:
658
659 return( ret );
660}
661
662/*
663 * Export X into unsigned binary data, big endian
664 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000666{
Paul Bakker23986e52011-04-24 08:57:21 +0000667 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000670
671 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000673
674 memset( buf, 0, buflen );
675
676 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
677 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
678
679 return( 0 );
680}
681
682/*
683 * Left-shift: X <<= count
684 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000686{
Paul Bakker23986e52011-04-24 08:57:21 +0000687 int ret;
688 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000690
691 v0 = count / (biL );
692 t1 = count & (biL - 1);
693
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200694 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000695
Paul Bakkerf9688572011-05-05 10:00:45 +0000696 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
699 ret = 0;
700
701 /*
702 * shift by count / limb_size
703 */
704 if( v0 > 0 )
705 {
Paul Bakker23986e52011-04-24 08:57:21 +0000706 for( i = X->n; i > v0; i-- )
707 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000708
Paul Bakker23986e52011-04-24 08:57:21 +0000709 for( ; i > 0; i-- )
710 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000711 }
712
713 /*
714 * shift by count % limb_size
715 */
716 if( t1 > 0 )
717 {
718 for( i = v0; i < X->n; i++ )
719 {
720 r1 = X->p[i] >> (biL - t1);
721 X->p[i] <<= t1;
722 X->p[i] |= r0;
723 r0 = r1;
724 }
725 }
726
727cleanup:
728
729 return( ret );
730}
731
732/*
733 * Right-shift: X >>= count
734 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200735int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000736{
Paul Bakker23986e52011-04-24 08:57:21 +0000737 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200738 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000739
740 v0 = count / biL;
741 v1 = count & (biL - 1);
742
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100743 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200744 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100745
Paul Bakker5121ce52009-01-03 21:22:43 +0000746 /*
747 * shift by count / limb_size
748 */
749 if( v0 > 0 )
750 {
751 for( i = 0; i < X->n - v0; i++ )
752 X->p[i] = X->p[i + v0];
753
754 for( ; i < X->n; i++ )
755 X->p[i] = 0;
756 }
757
758 /*
759 * shift by count % limb_size
760 */
761 if( v1 > 0 )
762 {
Paul Bakker23986e52011-04-24 08:57:21 +0000763 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000764 {
Paul Bakker23986e52011-04-24 08:57:21 +0000765 r1 = X->p[i - 1] << (biL - v1);
766 X->p[i - 1] >>= v1;
767 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000768 r0 = r1;
769 }
770 }
771
772 return( 0 );
773}
774
775/*
776 * Compare unsigned values
777 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200778int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000779{
Paul Bakker23986e52011-04-24 08:57:21 +0000780 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000781
Paul Bakker23986e52011-04-24 08:57:21 +0000782 for( i = X->n; i > 0; i-- )
783 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000784 break;
785
Paul Bakker23986e52011-04-24 08:57:21 +0000786 for( j = Y->n; j > 0; j-- )
787 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000788 break;
789
Paul Bakker23986e52011-04-24 08:57:21 +0000790 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000791 return( 0 );
792
793 if( i > j ) return( 1 );
794 if( j > i ) return( -1 );
795
Paul Bakker23986e52011-04-24 08:57:21 +0000796 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000797 {
Paul Bakker23986e52011-04-24 08:57:21 +0000798 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
799 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000800 }
801
802 return( 0 );
803}
804
805/*
806 * Compare signed values
807 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200808int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000809{
Paul Bakker23986e52011-04-24 08:57:21 +0000810 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000811
Paul Bakker23986e52011-04-24 08:57:21 +0000812 for( i = X->n; i > 0; i-- )
813 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000814 break;
815
Paul Bakker23986e52011-04-24 08:57:21 +0000816 for( j = Y->n; j > 0; j-- )
817 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000818 break;
819
Paul Bakker23986e52011-04-24 08:57:21 +0000820 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000821 return( 0 );
822
823 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000824 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000825
826 if( X->s > 0 && Y->s < 0 ) return( 1 );
827 if( Y->s > 0 && X->s < 0 ) return( -1 );
828
Paul Bakker23986e52011-04-24 08:57:21 +0000829 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000830 {
Paul Bakker23986e52011-04-24 08:57:21 +0000831 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
832 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000833 }
834
835 return( 0 );
836}
837
838/*
839 * Compare signed values
840 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200841int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000842{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200843 mbedtls_mpi Y;
844 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000845
846 *p = ( z < 0 ) ? -z : z;
847 Y.s = ( z < 0 ) ? -1 : 1;
848 Y.n = 1;
849 Y.p = p;
850
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200851 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000852}
853
854/*
855 * Unsigned addition: X = |A| + |B| (HAC 14.7)
856 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200857int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000858{
Paul Bakker23986e52011-04-24 08:57:21 +0000859 int ret;
860 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100861 mbedtls_mpi_uint *o, *p, c, tmp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000862
863 if( X == B )
864 {
Janos Follath6c922682015-10-30 17:43:11 +0100865 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000866 }
867
868 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200869 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200870
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000871 /*
872 * X should always be positive as a result of unsigned additions.
873 */
874 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000875
Paul Bakker23986e52011-04-24 08:57:21 +0000876 for( j = B->n; j > 0; j-- )
877 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000878 break;
879
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200880 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000881
882 o = B->p; p = X->p; c = 0;
883
Janos Follath6c922682015-10-30 17:43:11 +0100884 /*
885 * tmp is used because it might happen that p == o
886 */
Paul Bakker23986e52011-04-24 08:57:21 +0000887 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000888 {
Janos Follath6c922682015-10-30 17:43:11 +0100889 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000890 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100891 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000892 }
893
894 while( c != 0 )
895 {
896 if( i >= X->n )
897 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200898 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000899 p = X->p + i;
900 }
901
Paul Bakker2d319fd2012-09-16 21:34:26 +0000902 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000903 }
904
905cleanup:
906
907 return( ret );
908}
909
910/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200911 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000912 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200913static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000914{
Paul Bakker23986e52011-04-24 08:57:21 +0000915 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200916 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000917
918 for( i = c = 0; i < n; i++, s++, d++ )
919 {
920 z = ( *d < c ); *d -= c;
921 c = ( *d < *s ) + z; *d -= *s;
922 }
923
924 while( c != 0 )
925 {
926 z = ( *d < c ); *d -= c;
927 c = z; i++; d++;
928 }
929}
930
931/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100932 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000933 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200934int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000935{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200936 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000937 int ret;
938 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000939
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200940 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
941 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000942
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200943 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000944
945 if( X == B )
946 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000948 B = &TB;
949 }
950
951 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200952 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000953
Paul Bakker1ef7a532009-06-20 10:50:55 +0000954 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100955 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000956 */
957 X->s = 1;
958
Paul Bakker5121ce52009-01-03 21:22:43 +0000959 ret = 0;
960
Paul Bakker23986e52011-04-24 08:57:21 +0000961 for( n = B->n; n > 0; n-- )
962 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000963 break;
964
Paul Bakker23986e52011-04-24 08:57:21 +0000965 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000966
967cleanup:
968
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200969 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000970
971 return( ret );
972}
973
974/*
975 * Signed addition: X = A + B
976 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000978{
979 int ret, s = A->s;
980
981 if( A->s * B->s < 0 )
982 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200983 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000984 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200985 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000986 X->s = s;
987 }
988 else
989 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200990 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000991 X->s = -s;
992 }
993 }
994 else
995 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200996 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000997 X->s = s;
998 }
999
1000cleanup:
1001
1002 return( ret );
1003}
1004
1005/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001006 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001007 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001008int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001009{
1010 int ret, s = A->s;
1011
1012 if( A->s * B->s > 0 )
1013 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001014 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001015 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001017 X->s = s;
1018 }
1019 else
1020 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001021 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001022 X->s = -s;
1023 }
1024 }
1025 else
1026 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001027 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001028 X->s = s;
1029 }
1030
1031cleanup:
1032
1033 return( ret );
1034}
1035
1036/*
1037 * Signed addition: X = A + b
1038 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001039int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001040{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001041 mbedtls_mpi _B;
1042 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001043
1044 p[0] = ( b < 0 ) ? -b : b;
1045 _B.s = ( b < 0 ) ? -1 : 1;
1046 _B.n = 1;
1047 _B.p = p;
1048
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001049 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001050}
1051
1052/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001053 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001054 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001055int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001056{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001057 mbedtls_mpi _B;
1058 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001059
1060 p[0] = ( b < 0 ) ? -b : b;
1061 _B.s = ( b < 0 ) ? -1 : 1;
1062 _B.n = 1;
1063 _B.p = p;
1064
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001065 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001066}
1067
1068/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001069 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001070 */
1071static
1072#if defined(__APPLE__) && defined(__arm__)
1073/*
1074 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1075 * appears to need this to prevent bad ARM code generation at -O3.
1076 */
1077__attribute__ ((noinline))
1078#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001079void 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 +00001080{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001081 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001082
1083#if defined(MULADDC_HUIT)
1084 for( ; i >= 8; i -= 8 )
1085 {
1086 MULADDC_INIT
1087 MULADDC_HUIT
1088 MULADDC_STOP
1089 }
1090
1091 for( ; i > 0; i-- )
1092 {
1093 MULADDC_INIT
1094 MULADDC_CORE
1095 MULADDC_STOP
1096 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001097#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001098 for( ; i >= 16; i -= 16 )
1099 {
1100 MULADDC_INIT
1101 MULADDC_CORE MULADDC_CORE
1102 MULADDC_CORE MULADDC_CORE
1103 MULADDC_CORE MULADDC_CORE
1104 MULADDC_CORE MULADDC_CORE
1105
1106 MULADDC_CORE MULADDC_CORE
1107 MULADDC_CORE MULADDC_CORE
1108 MULADDC_CORE MULADDC_CORE
1109 MULADDC_CORE MULADDC_CORE
1110 MULADDC_STOP
1111 }
1112
1113 for( ; i >= 8; i -= 8 )
1114 {
1115 MULADDC_INIT
1116 MULADDC_CORE MULADDC_CORE
1117 MULADDC_CORE MULADDC_CORE
1118
1119 MULADDC_CORE MULADDC_CORE
1120 MULADDC_CORE MULADDC_CORE
1121 MULADDC_STOP
1122 }
1123
1124 for( ; i > 0; i-- )
1125 {
1126 MULADDC_INIT
1127 MULADDC_CORE
1128 MULADDC_STOP
1129 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001130#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001131
1132 t++;
1133
1134 do {
1135 *d += c; c = ( *d < c ); d++;
1136 }
1137 while( c != 0 );
1138}
1139
1140/*
1141 * Baseline multiplication: X = A * B (HAC 14.12)
1142 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001143int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001144{
Paul Bakker23986e52011-04-24 08:57:21 +00001145 int ret;
1146 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001147 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001148
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001149 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001150
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001151 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1152 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001153
Paul Bakker23986e52011-04-24 08:57:21 +00001154 for( i = A->n; i > 0; i-- )
1155 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001156 break;
1157
Paul Bakker23986e52011-04-24 08:57:21 +00001158 for( j = B->n; j > 0; j-- )
1159 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001160 break;
1161
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001162 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1163 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001164
Paul Bakker23986e52011-04-24 08:57:21 +00001165 for( i++; j > 0; j-- )
1166 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001167
1168 X->s = A->s * B->s;
1169
1170cleanup:
1171
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001172 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001173
1174 return( ret );
1175}
1176
1177/*
1178 * Baseline multiplication: X = A * b
1179 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001180int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001181{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001182 mbedtls_mpi _B;
1183 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001184
1185 _B.s = 1;
1186 _B.n = 1;
1187 _B.p = p;
1188 p[0] = b;
1189
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001190 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001191}
1192
1193/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001194 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001195 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001196int 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 +00001197{
Paul Bakker23986e52011-04-24 08:57:21 +00001198 int ret;
1199 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001200 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001202 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1203 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001204
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001205 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1206 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001207
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001208 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001209 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001210 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1211 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001212 return( 0 );
1213 }
1214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001215 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1216 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001217 X.s = Y.s = 1;
1218
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001219 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1220 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1221 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1222 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001223
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001224 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001225 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001226 {
1227 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001228 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1229 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001230 }
1231 else k = 0;
1232
1233 n = X.n - 1;
1234 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001235 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001236
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001237 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001238 {
1239 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001240 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001241 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001242 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001243
1244 for( i = n; i > t ; i-- )
1245 {
1246 if( X.p[i] >= Y.p[t] )
1247 Z.p[i - t - 1] = ~0;
1248 else
1249 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001250#if defined(MBEDTLS_HAVE_UDBL)
1251 mbedtls_t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001252
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001253 r = (mbedtls_t_udbl) X.p[i] << biL;
1254 r |= (mbedtls_t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001255 r /= Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001256 if( r > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1257 r = ( (mbedtls_t_udbl) 1 << biL ) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001259 Z.p[i - t - 1] = (mbedtls_mpi_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001260#else
1261 /*
1262 * __udiv_qrnnd_c, from gmp/longlong.h
1263 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001264 mbedtls_mpi_uint q0, q1, r0, r1;
1265 mbedtls_mpi_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001266
1267 d = Y.p[t];
1268 d0 = ( d << biH ) >> biH;
1269 d1 = ( d >> biH );
1270
1271 q1 = X.p[i] / d1;
1272 r1 = X.p[i] - d1 * q1;
1273 r1 <<= biH;
1274 r1 |= ( X.p[i - 1] >> biH );
1275
1276 m = q1 * d0;
1277 if( r1 < m )
1278 {
1279 q1--, r1 += d;
1280 while( r1 >= d && r1 < m )
1281 q1--, r1 += d;
1282 }
1283 r1 -= m;
1284
1285 q0 = r1 / d1;
1286 r0 = r1 - d1 * q0;
1287 r0 <<= biH;
1288 r0 |= ( X.p[i - 1] << biH ) >> biH;
1289
1290 m = q0 * d0;
1291 if( r0 < m )
1292 {
1293 q0--, r0 += d;
1294 while( r0 >= d && r0 < m )
1295 q0--, r0 += d;
1296 }
1297 r0 -= m;
1298
1299 Z.p[i - t - 1] = ( q1 << biH ) | q0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001300#endif /* MBEDTLS_HAVE_UDBL && !64-bit Apple with Clang 5.0 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001301 }
1302
1303 Z.p[i - t - 1]++;
1304 do
1305 {
1306 Z.p[i - t - 1]--;
1307
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001308 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001309 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001310 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001311 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001312
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001313 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001314 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1315 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001316 T2.p[2] = X.p[i];
1317 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001318 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001320 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1321 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1322 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001324 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001325 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001326 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1327 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1328 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001329 Z.p[i - t - 1]--;
1330 }
1331 }
1332
1333 if( Q != NULL )
1334 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001335 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001336 Q->s = A->s * B->s;
1337 }
1338
1339 if( R != NULL )
1340 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001341 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001342 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001343 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001345 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001346 R->s = 1;
1347 }
1348
1349cleanup:
1350
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001351 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1352 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001353
1354 return( ret );
1355}
1356
1357/*
1358 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001359 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001360int 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 +00001361{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001362 mbedtls_mpi _B;
1363 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001364
1365 p[0] = ( b < 0 ) ? -b : b;
1366 _B.s = ( b < 0 ) ? -1 : 1;
1367 _B.n = 1;
1368 _B.p = p;
1369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001370 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001371}
1372
1373/*
1374 * Modulo: R = A mod B
1375 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001376int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001377{
1378 int ret;
1379
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001380 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1381 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001383 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001385 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1386 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001387
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001388 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1389 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001390
1391cleanup:
1392
1393 return( ret );
1394}
1395
1396/*
1397 * Modulo: r = A mod b
1398 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001400{
Paul Bakker23986e52011-04-24 08:57:21 +00001401 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001402 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001403
1404 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001405 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001406
1407 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001408 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001409
1410 /*
1411 * handle trivial cases
1412 */
1413 if( b == 1 )
1414 {
1415 *r = 0;
1416 return( 0 );
1417 }
1418
1419 if( b == 2 )
1420 {
1421 *r = A->p[0] & 1;
1422 return( 0 );
1423 }
1424
1425 /*
1426 * general case
1427 */
Paul Bakker23986e52011-04-24 08:57:21 +00001428 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001429 {
Paul Bakker23986e52011-04-24 08:57:21 +00001430 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001431 y = ( y << biH ) | ( x >> biH );
1432 z = y / b;
1433 y -= z * b;
1434
1435 x <<= biH;
1436 y = ( y << biH ) | ( x >> biH );
1437 z = y / b;
1438 y -= z * b;
1439 }
1440
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001441 /*
1442 * If A is negative, then the current y represents a negative value.
1443 * Flipping it to the positive side.
1444 */
1445 if( A->s < 0 && y != 0 )
1446 y = b - y;
1447
Paul Bakker5121ce52009-01-03 21:22:43 +00001448 *r = y;
1449
1450 return( 0 );
1451}
1452
1453/*
1454 * Fast Montgomery initialization (thanks to Tom St Denis)
1455 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001456static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001457{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001458 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001459 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001460
1461 x = m0;
1462 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001463
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001464 for( i = biL; i >= 8; i /= 2 )
1465 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001466
1467 *mm = ~x + 1;
1468}
1469
1470/*
1471 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1472 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001473static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1474 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001475{
Paul Bakker23986e52011-04-24 08:57:21 +00001476 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001477 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001478
1479 memset( T->p, 0, T->n * ciL );
1480
1481 d = T->p;
1482 n = N->n;
1483 m = ( B->n < n ) ? B->n : n;
1484
1485 for( i = 0; i < n; i++ )
1486 {
1487 /*
1488 * T = (T + u0*B + u1*N) / 2^biL
1489 */
1490 u0 = A->p[i];
1491 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1492
1493 mpi_mul_hlp( m, B->p, d, u0 );
1494 mpi_mul_hlp( n, N->p, d, u1 );
1495
1496 *d++ = u0; d[n + 1] = 0;
1497 }
1498
Paul Bakker66d5d072014-06-17 16:39:18 +02001499 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001500
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001501 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001502 mpi_sub_hlp( n, N->p, A->p );
1503 else
1504 /* prevent timing attacks */
1505 mpi_sub_hlp( n, A->p, T->p );
1506}
1507
1508/*
1509 * Montgomery reduction: A = A * R^-1 mod N
1510 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511static 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 +00001512{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001513 mbedtls_mpi_uint z = 1;
1514 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001515
Paul Bakker8ddb6452013-02-27 14:56:33 +01001516 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001517 U.p = &z;
1518
1519 mpi_montmul( A, &U, N, mm, T );
1520}
1521
1522/*
1523 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1524 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001525int 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 +00001526{
Paul Bakker23986e52011-04-24 08:57:21 +00001527 int ret;
1528 size_t wbits, wsize, one = 1;
1529 size_t i, j, nblimbs;
1530 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001531 mbedtls_mpi_uint ei, mm, state;
1532 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001533 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001534
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001535 if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
1536 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001537
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001538 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1539 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001540
1541 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001542 * Init temps and window size
1543 */
1544 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001545 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1546 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001547 memset( W, 0, sizeof( W ) );
1548
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001549 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001550
1551 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1552 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001554 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1555 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001556
Paul Bakker5121ce52009-01-03 21:22:43 +00001557 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001558 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1559 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1560 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001561
1562 /*
Paul Bakker50546922012-05-19 08:40:49 +00001563 * Compensate for negative A (and correct at the end)
1564 */
1565 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001566 if( neg )
1567 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001568 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001569 Apos.s = 1;
1570 A = &Apos;
1571 }
1572
1573 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001574 * If 1st call, pre-compute R^2 mod N
1575 */
1576 if( _RR == NULL || _RR->p == NULL )
1577 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001578 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1579 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1580 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001581
1582 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001583 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001584 }
1585 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001586 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001587
1588 /*
1589 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1590 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001591 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1592 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001593 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001594 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001595
1596 mpi_montmul( &W[1], &RR, N, mm, &T );
1597
1598 /*
1599 * X = R^2 * R^-1 mod N = R mod N
1600 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001601 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001602 mpi_montred( X, N, mm, &T );
1603
1604 if( wsize > 1 )
1605 {
1606 /*
1607 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1608 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001609 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001610
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001611 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1612 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001613
1614 for( i = 0; i < wsize - 1; i++ )
1615 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001616
Paul Bakker5121ce52009-01-03 21:22:43 +00001617 /*
1618 * W[i] = W[i - 1] * W[1]
1619 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001620 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001621 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001622 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1623 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001624
1625 mpi_montmul( &W[i], &W[1], N, mm, &T );
1626 }
1627 }
1628
1629 nblimbs = E->n;
1630 bufsize = 0;
1631 nbits = 0;
1632 wbits = 0;
1633 state = 0;
1634
1635 while( 1 )
1636 {
1637 if( bufsize == 0 )
1638 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001639 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001640 break;
1641
Paul Bakker0d7702c2013-10-29 16:18:35 +01001642 nblimbs--;
1643
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001644 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001645 }
1646
1647 bufsize--;
1648
1649 ei = (E->p[nblimbs] >> bufsize) & 1;
1650
1651 /*
1652 * skip leading 0s
1653 */
1654 if( ei == 0 && state == 0 )
1655 continue;
1656
1657 if( ei == 0 && state == 1 )
1658 {
1659 /*
1660 * out of window, square X
1661 */
1662 mpi_montmul( X, X, N, mm, &T );
1663 continue;
1664 }
1665
1666 /*
1667 * add ei to current window
1668 */
1669 state = 2;
1670
1671 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001672 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001673
1674 if( nbits == wsize )
1675 {
1676 /*
1677 * X = X^wsize R^-1 mod N
1678 */
1679 for( i = 0; i < wsize; i++ )
1680 mpi_montmul( X, X, N, mm, &T );
1681
1682 /*
1683 * X = X * W[wbits] R^-1 mod N
1684 */
1685 mpi_montmul( X, &W[wbits], N, mm, &T );
1686
1687 state--;
1688 nbits = 0;
1689 wbits = 0;
1690 }
1691 }
1692
1693 /*
1694 * process the remaining bits
1695 */
1696 for( i = 0; i < nbits; i++ )
1697 {
1698 mpi_montmul( X, X, N, mm, &T );
1699
1700 wbits <<= 1;
1701
Paul Bakker66d5d072014-06-17 16:39:18 +02001702 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001703 mpi_montmul( X, &W[1], N, mm, &T );
1704 }
1705
1706 /*
1707 * X = A^E * R * R^-1 mod N = A^E mod N
1708 */
1709 mpi_montred( X, N, mm, &T );
1710
Paul Bakkerf6198c12012-05-16 08:02:29 +00001711 if( neg )
1712 {
1713 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001714 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001715 }
1716
Paul Bakker5121ce52009-01-03 21:22:43 +00001717cleanup:
1718
Paul Bakker66d5d072014-06-17 16:39:18 +02001719 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001720 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001721
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001722 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001723
Paul Bakker75a28602014-03-31 12:08:17 +02001724 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001725 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001726
1727 return( ret );
1728}
1729
Paul Bakker5121ce52009-01-03 21:22:43 +00001730/*
1731 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1732 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001733int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001734{
Paul Bakker23986e52011-04-24 08:57:21 +00001735 int ret;
1736 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001737 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001738
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001739 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001740
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001741 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1742 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001743
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001744 lz = mbedtls_mpi_lsb( &TA );
1745 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001746
Paul Bakker66d5d072014-06-17 16:39:18 +02001747 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001748 lz = lzt;
1749
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001750 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1751 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001752
Paul Bakker5121ce52009-01-03 21:22:43 +00001753 TA.s = TB.s = 1;
1754
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001756 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001757 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1758 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001759
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001760 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001761 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001762 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1763 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001764 }
1765 else
1766 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001767 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1768 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001769 }
1770 }
1771
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001772 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1773 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001774
1775cleanup:
1776
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001777 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001778
1779 return( ret );
1780}
1781
Paul Bakker33dc46b2014-04-30 16:11:39 +02001782/*
1783 * Fill X with size bytes of random.
1784 *
1785 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001786 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001787 * deterministic, eg for tests).
1788 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001789int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001790 int (*f_rng)(void *, unsigned char *, size_t),
1791 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001792{
Paul Bakker23986e52011-04-24 08:57:21 +00001793 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001794 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001795
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001796 if( size > MBEDTLS_MPI_MAX_SIZE )
1797 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001798
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001799 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1800 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001801
1802cleanup:
1803 return( ret );
1804}
1805
Paul Bakker5121ce52009-01-03 21:22:43 +00001806/*
1807 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1808 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001809int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001810{
1811 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001812 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001813
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001814 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 )
1815 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001816
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001817 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1818 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1819 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001820
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001821 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001822
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001823 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001824 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001825 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001826 goto cleanup;
1827 }
1828
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001829 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1830 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1831 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1832 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001833
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001834 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1835 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1836 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1837 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001838
1839 do
1840 {
1841 while( ( TU.p[0] & 1 ) == 0 )
1842 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001843 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001844
1845 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1846 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001847 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1848 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001849 }
1850
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001851 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1852 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001853 }
1854
1855 while( ( TV.p[0] & 1 ) == 0 )
1856 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001857 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001858
1859 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1860 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001861 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1862 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001863 }
1864
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001865 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1866 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001867 }
1868
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001869 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001870 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001871 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1872 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1873 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001874 }
1875 else
1876 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001877 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1878 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1879 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001880 }
1881 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001883
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001884 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1885 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001886
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001887 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1888 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001889
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001890 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001891
1892cleanup:
1893
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1895 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1896 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001897
1898 return( ret );
1899}
1900
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001901#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001902
Paul Bakker5121ce52009-01-03 21:22:43 +00001903static const int small_prime[] =
1904{
1905 3, 5, 7, 11, 13, 17, 19, 23,
1906 29, 31, 37, 41, 43, 47, 53, 59,
1907 61, 67, 71, 73, 79, 83, 89, 97,
1908 101, 103, 107, 109, 113, 127, 131, 137,
1909 139, 149, 151, 157, 163, 167, 173, 179,
1910 181, 191, 193, 197, 199, 211, 223, 227,
1911 229, 233, 239, 241, 251, 257, 263, 269,
1912 271, 277, 281, 283, 293, 307, 311, 313,
1913 317, 331, 337, 347, 349, 353, 359, 367,
1914 373, 379, 383, 389, 397, 401, 409, 419,
1915 421, 431, 433, 439, 443, 449, 457, 461,
1916 463, 467, 479, 487, 491, 499, 503, 509,
1917 521, 523, 541, 547, 557, 563, 569, 571,
1918 577, 587, 593, 599, 601, 607, 613, 617,
1919 619, 631, 641, 643, 647, 653, 659, 661,
1920 673, 677, 683, 691, 701, 709, 719, 727,
1921 733, 739, 743, 751, 757, 761, 769, 773,
1922 787, 797, 809, 811, 821, 823, 827, 829,
1923 839, 853, 857, 859, 863, 877, 881, 883,
1924 887, 907, 911, 919, 929, 937, 941, 947,
1925 953, 967, 971, 977, 983, 991, 997, -103
1926};
1927
1928/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001929 * Small divisors test (X must be positive)
1930 *
1931 * Return values:
1932 * 0: no small factor (possible prime, more tests needed)
1933 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001934 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001935 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00001936 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001937static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00001938{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001939 int ret = 0;
1940 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001941 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001942
Paul Bakker5121ce52009-01-03 21:22:43 +00001943 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001944 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
1946 for( i = 0; small_prime[i] > 0; i++ )
1947 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001948 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001949 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001950
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001951 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001952
1953 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001954 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001955 }
1956
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001957cleanup:
1958 return( ret );
1959}
1960
1961/*
1962 * Miller-Rabin pseudo-primality test (HAC 4.24)
1963 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001964static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001965 int (*f_rng)(void *, unsigned char *, size_t),
1966 void *p_rng )
1967{
Pascal Junodb99183d2015-03-11 16:49:45 +01001968 int ret, count;
1969 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001970 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001971
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001972 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
1973 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001974
Paul Bakker5121ce52009-01-03 21:22:43 +00001975 /*
1976 * W = |X| - 1
1977 * R = W >> lsb( W )
1978 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001979 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
1980 s = mbedtls_mpi_lsb( &W );
1981 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
1982 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001983
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001984 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00001985 /*
1986 * HAC, table 4.4
1987 */
1988 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1989 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1990 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1991
1992 for( i = 0; i < n; i++ )
1993 {
1994 /*
1995 * pick a random A, 1 < A < |X| - 1
1996 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001997 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001998
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001999 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00002000 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002001 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002002 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00002003 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002004 A.p[0] |= 3;
2005
Pascal Junodb99183d2015-03-11 16:49:45 +01002006 count = 0;
2007 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002008 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002009
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002010 j = mbedtls_mpi_bitlen( &A );
2011 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002012 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002013 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002014 }
2015
2016 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002017 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002018 }
2019
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002020 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2021 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
2023 /*
2024 * A = A^R mod |X|
2025 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002026 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002027
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002028 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2029 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002030 continue;
2031
2032 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002033 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002034 {
2035 /*
2036 * A = A * A mod |X|
2037 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002038 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2039 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002040
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002041 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002042 break;
2043
2044 j++;
2045 }
2046
2047 /*
2048 * not prime if A != |X| - 1 or A == 1
2049 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002050 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2051 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002052 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002053 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002054 break;
2055 }
2056 }
2057
2058cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002059 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2060 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002061
2062 return( ret );
2063}
2064
2065/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002066 * Pseudo-primality test: small factors, then Miller-Rabin
2067 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002068int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002069 int (*f_rng)(void *, unsigned char *, size_t),
2070 void *p_rng )
2071{
2072 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002073 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002074
2075 XX.s = 1;
2076 XX.n = X->n;
2077 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002078
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002079 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2080 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2081 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002082
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002083 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002084 return( 0 );
2085
2086 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2087 {
2088 if( ret == 1 )
2089 return( 0 );
2090
2091 return( ret );
2092 }
2093
2094 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2095}
2096
2097/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002098 * Prime number generation
2099 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002100int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002101 int (*f_rng)(void *, unsigned char *, size_t),
2102 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002103{
Paul Bakker23986e52011-04-24 08:57:21 +00002104 int ret;
2105 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002106 mbedtls_mpi_uint r;
2107 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002108
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002109 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2110 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002111
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002112 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002113
2114 n = BITS_TO_LIMBS( nbits );
2115
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002116 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002117
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002118 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002119 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002120
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002121 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002122
2123 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002124
2125 if( dh_flag == 0 )
2126 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002127 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002128 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002129 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002130 goto cleanup;
2131
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002132 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002133 }
2134 }
2135 else
2136 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002137 /*
2138 * An necessary condition for Y and X = 2Y + 1 to be prime
2139 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2140 * Make sure it is satisfied, while keeping X = 3 mod 4
2141 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002142
2143 X->p[0] |= 2;
2144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002146 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002147 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002148 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002149 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002150
2151 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002152 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2153 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002154
2155 while( 1 )
2156 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002157 /*
2158 * First, check small factors for X and Y
2159 * before doing Miller-Rabin on any of them
2160 */
2161 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2162 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2163 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2164 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002165 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002166 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002167 }
2168
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002169 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002170 goto cleanup;
2171
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002172 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002173 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002174 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2175 * so up Y by 6 and X by 12.
2176 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2178 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002179 }
2180 }
2181
2182cleanup:
2183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002185
2186 return( ret );
2187}
2188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002189#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002190
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002191#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002192
Paul Bakker23986e52011-04-24 08:57:21 +00002193#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002194
2195static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2196{
2197 { 693, 609, 21 },
2198 { 1764, 868, 28 },
2199 { 768454923, 542167814, 1 }
2200};
2201
Paul Bakker5121ce52009-01-03 21:22:43 +00002202/*
2203 * Checkup routine
2204 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002205int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002206{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002207 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002208 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002210 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2211 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002212
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002213 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002214 "EFE021C2645FD1DC586E69184AF4A31E" \
2215 "D5F53E93B5F123FA41680867BA110131" \
2216 "944FE7952E2517337780CB0DB80E61AA" \
2217 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2218
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002219 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002220 "B2E7EFD37075B9F03FF989C7C5051C20" \
2221 "34D2A323810251127E7BF8625A4F49A5" \
2222 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2223 "5B5C25763222FEFCCFC38B832366C29E" ) );
2224
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002225 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002226 "0066A198186C18C10B2F5ED9B522752A" \
2227 "9830B69916E535C8F047518A889A43A5" \
2228 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2229
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002230 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002231
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002232 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002233 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2234 "9E857EA95A03512E2BAE7391688D264A" \
2235 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2236 "8001B72E848A38CAE1C65F78E56ABDEF" \
2237 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2238 "ECF677152EF804370C1A305CAF3B5BF1" \
2239 "30879B56C61DE584A0F53A2447A51E" ) );
2240
2241 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002242 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002243
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002244 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002245 {
2246 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002247 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002248
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002249 ret = 1;
2250 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002251 }
2252
2253 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002254 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002255
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002256 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002257
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002258 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002259 "256567336059E52CAE22925474705F39A94" ) );
2260
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002261 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002262 "6613F26162223DF488E9CD48CC132C7A" \
2263 "0AC93C701B001B092E4E5B9F73BCD27B" \
2264 "9EE50D0657C77F374E903CDFA4C642" ) );
2265
2266 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002267 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002268
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002269 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2270 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002271 {
2272 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002273 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002274
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002275 ret = 1;
2276 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002277 }
2278
2279 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002280 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002281
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002282 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002283
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002284 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002285 "36E139AEA55215609D2816998ED020BB" \
2286 "BD96C37890F65171D948E9BC7CBAA4D9" \
2287 "325D24D6A3C12710F10A09FA08AB87" ) );
2288
2289 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002290 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002291
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002292 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002293 {
2294 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002295 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002296
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002297 ret = 1;
2298 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002299 }
2300
2301 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002302 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002303
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002304 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002305
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002306 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002307 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2308 "C3DBA76456363A10869622EAC2DD84EC" \
2309 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2310
2311 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002312 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002313
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002314 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002315 {
2316 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002317 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002318
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002319 ret = 1;
2320 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002321 }
2322
2323 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002324 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002325
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002326 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002327 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002328
Paul Bakker66d5d072014-06-17 16:39:18 +02002329 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002330 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002331 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2332 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002334 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002336 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002337 {
2338 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002339 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002340
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002341 ret = 1;
2342 goto cleanup;
2343 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002344 }
2345
2346 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002348
Paul Bakker5121ce52009-01-03 21:22:43 +00002349cleanup:
2350
2351 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002352 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002354 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2355 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002356
2357 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002358 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002359
2360 return( ret );
2361}
2362
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002363#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002364
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002365#endif /* MBEDTLS_BIGNUM_C */