blob: 7e35aa69968a23dfc8b1aa4ad2e5775ba1ba5729 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
21/*
22 * This MPI implementation is based on:
23 *
24 * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020025 * http://www.stillhq.com/extracted/gnupg-api/mbedtls_mpi/
Paul Bakker5121ce52009-01-03 21:22:43 +000026 * http://math.libtomcrypt.com/files/tommath.pdf
27 */
28
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020029#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000030#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020031#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020033#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000034
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000036
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000037#include "mbedtls/bignum.h"
38#include "mbedtls/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000039
Rich Evans00ab4702015-02-06 13:43:58 +000040#include <string.h>
41
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020042#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000043#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020044#else
Rich Evans00ab4702015-02-06 13:43:58 +000045#include <stdio.h>
46#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020047#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020048#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020050#endif
51
Paul Bakker34617722014-06-13 17:20:13 +020052/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020053static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020054 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
55}
56
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000058#define biL (ciL << 3) /* bits in limb */
59#define biH (ciL << 2) /* half limb size */
60
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010061#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
62
Paul Bakker5121ce52009-01-03 21:22:43 +000063/*
64 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020065 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000066 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020067#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
68#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000069
70/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000071 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000072 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020073void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000074{
Paul Bakker6c591fa2011-05-05 11:49:20 +000075 if( X == NULL )
76 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000077
Paul Bakker6c591fa2011-05-05 11:49:20 +000078 X->s = 1;
79 X->n = 0;
80 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000081}
82
83/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000084 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000085 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020086void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000087{
Paul Bakker6c591fa2011-05-05 11:49:20 +000088 if( X == NULL )
89 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000090
Paul Bakker6c591fa2011-05-05 11:49:20 +000091 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +000092 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020093 mbedtls_zeroize( X->p, X->n * ciL );
94 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +000095 }
96
Paul Bakker6c591fa2011-05-05 11:49:20 +000097 X->s = 1;
98 X->n = 0;
99 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000100}
101
102/*
103 * Enlarge to the specified number of limbs
104 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200105int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000106{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200107 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000108
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200110 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000111
Paul Bakker5121ce52009-01-03 21:22:43 +0000112 if( X->n < nblimbs )
113 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200114 if( ( p = mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200115 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000116
Paul Bakker5121ce52009-01-03 21:22:43 +0000117 if( X->p != NULL )
118 {
119 memcpy( p, X->p, X->n * ciL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120 mbedtls_zeroize( X->p, X->n * ciL );
121 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000122 }
123
124 X->n = nblimbs;
125 X->p = p;
126 }
127
128 return( 0 );
129}
130
131/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100132 * Resize down as much as possible,
133 * while keeping at least the specified number of limbs
134 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100136{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100138 size_t i;
139
140 /* Actually resize up in this case */
141 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200142 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100143
144 for( i = X->n - 1; i > 0; i-- )
145 if( X->p[i] != 0 )
146 break;
147 i++;
148
149 if( i < nblimbs )
150 i = nblimbs;
151
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200152 if( ( p = mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200153 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100155 if( X->p != NULL )
156 {
157 memcpy( p, X->p, i * ciL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 mbedtls_zeroize( X->p, X->n * ciL );
159 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100160 }
161
162 X->n = i;
163 X->p = p;
164
165 return( 0 );
166}
167
168/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000169 * Copy the contents of Y into X
170 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000172{
Paul Bakker23986e52011-04-24 08:57:21 +0000173 int ret;
174 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000175
176 if( X == Y )
177 return( 0 );
178
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200179 if( Y->p == NULL )
180 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200182 return( 0 );
183 }
184
Paul Bakker5121ce52009-01-03 21:22:43 +0000185 for( i = Y->n - 1; i > 0; i-- )
186 if( Y->p[i] != 0 )
187 break;
188 i++;
189
190 X->s = Y->s;
191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200192 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000193
194 memset( X->p, 0, X->n * ciL );
195 memcpy( X->p, Y->p, i * ciL );
196
197cleanup:
198
199 return( ret );
200}
201
202/*
203 * Swap the contents of X and Y
204 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000206{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209 memcpy( &T, X, sizeof( mbedtls_mpi ) );
210 memcpy( X, Y, sizeof( mbedtls_mpi ) );
211 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000212}
213
214/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100215 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100216 * about whether the assignment was made or not.
217 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100218 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100220{
221 int ret = 0;
222 size_t i;
223
Pascal Junodb99183d2015-03-11 16:49:45 +0100224 /* make sure assign is 0 or 1 in a time-constant manner */
225 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200227 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100228
Paul Bakker66d5d072014-06-17 16:39:18 +0200229 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100230
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100231 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200232 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100233
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100234 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200235 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100236
237cleanup:
238 return( ret );
239}
240
241/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100242 * Conditionally swap X and Y, without leaking information
243 * about whether the swap was made or not.
244 * Here it is not ok to simply swap the pointers, which whould lead to
245 * different memory access patterns when X and Y are used afterwards.
246 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100248{
249 int ret, s;
250 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200251 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100252
253 if( X == Y )
254 return( 0 );
255
Pascal Junodb99183d2015-03-11 16:49:45 +0100256 /* make sure swap is 0 or 1 in a time-constant manner */
257 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
260 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100261
262 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200263 X->s = X->s * ( 1 - swap ) + Y->s * swap;
264 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100265
266
267 for( i = 0; i < X->n; i++ )
268 {
269 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200270 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
271 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100272 }
273
274cleanup:
275 return( ret );
276}
277
278/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000279 * Set value from integer
280 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000282{
283 int ret;
284
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200285 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000286 memset( X->p, 0, X->n * ciL );
287
288 X->p[0] = ( z < 0 ) ? -z : z;
289 X->s = ( z < 0 ) ? -1 : 1;
290
291cleanup:
292
293 return( ret );
294}
295
296/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000297 * Get a specific bit
298 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000300{
301 if( X->n * biL <= pos )
302 return( 0 );
303
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200304 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000305}
306
307/*
308 * Set a bit to a specific value of 0 or 1
309 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200310int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000311{
312 int ret = 0;
313 size_t off = pos / biL;
314 size_t idx = pos % biL;
315
316 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200317 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200318
Paul Bakker2f5947e2011-05-18 15:47:11 +0000319 if( X->n * biL <= pos )
320 {
321 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200322 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200324 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000325 }
326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
328 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000329
330cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200331
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332 return( ret );
333}
334
335/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200336 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000337 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200338size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000339{
Paul Bakker23986e52011-04-24 08:57:21 +0000340 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000341
342 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000343 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000344 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
345 return( count );
346
347 return( 0 );
348}
349
350/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200351 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000352 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200353size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000354{
Paul Bakker23986e52011-04-24 08:57:21 +0000355 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000356
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200357 if( X->n == 0 )
358 return( 0 );
359
Paul Bakker5121ce52009-01-03 21:22:43 +0000360 for( i = X->n - 1; i > 0; i-- )
361 if( X->p[i] != 0 )
362 break;
363
Paul Bakker23986e52011-04-24 08:57:21 +0000364 for( j = biL; j > 0; j-- )
365 if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000366 break;
367
Paul Bakker23986e52011-04-24 08:57:21 +0000368 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000369}
370
371/*
372 * Return the total size in bytes
373 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200374size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000375{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200376 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000377}
378
379/*
380 * Convert an ASCII character to digit value
381 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000383{
384 *d = 255;
385
386 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
387 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
388 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200390 if( *d >= (mbedtls_mpi_uint) radix )
391 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000392
393 return( 0 );
394}
395
396/*
397 * Import from an ASCII string
398 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000400{
Paul Bakker23986e52011-04-24 08:57:21 +0000401 int ret;
402 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200403 mbedtls_mpi_uint d;
404 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000405
406 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000410
Paul Bakkerff60ee62010-03-16 21:09:09 +0000411 slen = strlen( s );
412
Paul Bakker5121ce52009-01-03 21:22:43 +0000413 if( radix == 16 )
414 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100415 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200416 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
417
Paul Bakkerff60ee62010-03-16 21:09:09 +0000418 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000419
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200420 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
421 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000422
Paul Bakker23986e52011-04-24 08:57:21 +0000423 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000424 {
Paul Bakker23986e52011-04-24 08:57:21 +0000425 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000426 {
427 X->s = -1;
428 break;
429 }
430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200431 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200432 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000433 }
434 }
435 else
436 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000438
Paul Bakkerff60ee62010-03-16 21:09:09 +0000439 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000440 {
441 if( i == 0 && s[i] == '-' )
442 {
443 X->s = -1;
444 continue;
445 }
446
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200447 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
448 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000449
450 if( X->s == 1 )
451 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000453 }
454 else
455 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000457 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 }
459 }
460
461cleanup:
462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000464
465 return( ret );
466}
467
468/*
469 * Helper to write the digits high-order first
470 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000472{
473 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000475
476 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000478
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
480 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
483 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000484
485 if( r < 10 )
486 *(*p)++ = (char)( r + 0x30 );
487 else
488 *(*p)++ = (char)( r + 0x37 );
489
490cleanup:
491
492 return( ret );
493}
494
495/*
496 * Export into an ASCII string
497 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100498int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
499 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000500{
Paul Bakker23986e52011-04-24 08:57:21 +0000501 int ret = 0;
502 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000503 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000505
506 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000508
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200509 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000510 if( radix >= 4 ) n >>= 1;
511 if( radix >= 16 ) n >>= 1;
512 n += 3;
513
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100514 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000515 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100516 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000518 }
519
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100520 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000522
523 if( X->s == -1 )
524 *p++ = '-';
525
526 if( radix == 16 )
527 {
Paul Bakker23986e52011-04-24 08:57:21 +0000528 int c;
529 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000530
Paul Bakker23986e52011-04-24 08:57:21 +0000531 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000532 {
Paul Bakker23986e52011-04-24 08:57:21 +0000533 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000534 {
Paul Bakker23986e52011-04-24 08:57:21 +0000535 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000536
Paul Bakker6c343d72014-07-10 14:36:19 +0200537 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000538 continue;
539
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000540 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000541 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000542 k = 1;
543 }
544 }
545 }
546 else
547 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200548 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000549
550 if( T.s == -1 )
551 T.s = 1;
552
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000554 }
555
556 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100557 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000558
559cleanup:
560
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200561 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000562
563 return( ret );
564}
565
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000567/*
568 * Read X from an opened file
569 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200570int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000571{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200572 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000573 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000574 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000575 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000576 * Buffer should have space for (short) label and decimal formatted MPI,
577 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000578 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200579 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000580
581 memset( s, 0, sizeof( s ) );
582 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200583 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
585 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000586 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200587 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000588
Paul Bakker5121ce52009-01-03 21:22:43 +0000589 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
590 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
591
592 p = s + slen;
593 while( --p >= s )
594 if( mpi_get_digit( &d, radix, *p ) != 0 )
595 break;
596
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000598}
599
600/*
601 * Write X into an opened file (or stdout if fout == NULL)
602 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000604{
Paul Bakker23986e52011-04-24 08:57:21 +0000605 int ret;
606 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000607 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000608 * Buffer should have space for (short) label and decimal formatted MPI,
609 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000610 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000612
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100613 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000614
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100615 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000616
617 if( p == NULL ) p = "";
618
619 plen = strlen( p );
620 slen = strlen( s );
621 s[slen++] = '\r';
622 s[slen++] = '\n';
623
624 if( fout != NULL )
625 {
626 if( fwrite( p, 1, plen, fout ) != plen ||
627 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000629 }
630 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000632
633cleanup:
634
635 return( ret );
636}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000638
639/*
640 * Import X from unsigned binary data, big endian
641 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000643{
Paul Bakker23986e52011-04-24 08:57:21 +0000644 int ret;
645 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000646
647 for( n = 0; n < buflen; n++ )
648 if( buf[n] != 0 )
649 break;
650
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
652 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000653
Paul Bakker23986e52011-04-24 08:57:21 +0000654 for( i = buflen, j = 0; i > n; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000656
657cleanup:
658
659 return( ret );
660}
661
662/*
663 * Export X into unsigned binary data, big endian
664 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000666{
Paul Bakker23986e52011-04-24 08:57:21 +0000667 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000670
671 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000673
674 memset( buf, 0, buflen );
675
676 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
677 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
678
679 return( 0 );
680}
681
682/*
683 * Left-shift: X <<= count
684 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000686{
Paul Bakker23986e52011-04-24 08:57:21 +0000687 int ret;
688 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000690
691 v0 = count / (biL );
692 t1 = count & (biL - 1);
693
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200694 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000695
Paul Bakkerf9688572011-05-05 10:00:45 +0000696 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
699 ret = 0;
700
701 /*
702 * shift by count / limb_size
703 */
704 if( v0 > 0 )
705 {
Paul Bakker23986e52011-04-24 08:57:21 +0000706 for( i = X->n; i > v0; i-- )
707 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000708
Paul Bakker23986e52011-04-24 08:57:21 +0000709 for( ; i > 0; i-- )
710 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000711 }
712
713 /*
714 * shift by count % limb_size
715 */
716 if( t1 > 0 )
717 {
718 for( i = v0; i < X->n; i++ )
719 {
720 r1 = X->p[i] >> (biL - t1);
721 X->p[i] <<= t1;
722 X->p[i] |= r0;
723 r0 = r1;
724 }
725 }
726
727cleanup:
728
729 return( ret );
730}
731
732/*
733 * Right-shift: X >>= count
734 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200735int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000736{
Paul Bakker23986e52011-04-24 08:57:21 +0000737 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200738 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000739
740 v0 = count / biL;
741 v1 = count & (biL - 1);
742
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100743 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200744 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100745
Paul Bakker5121ce52009-01-03 21:22:43 +0000746 /*
747 * shift by count / limb_size
748 */
749 if( v0 > 0 )
750 {
751 for( i = 0; i < X->n - v0; i++ )
752 X->p[i] = X->p[i + v0];
753
754 for( ; i < X->n; i++ )
755 X->p[i] = 0;
756 }
757
758 /*
759 * shift by count % limb_size
760 */
761 if( v1 > 0 )
762 {
Paul Bakker23986e52011-04-24 08:57:21 +0000763 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000764 {
Paul Bakker23986e52011-04-24 08:57:21 +0000765 r1 = X->p[i - 1] << (biL - v1);
766 X->p[i - 1] >>= v1;
767 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000768 r0 = r1;
769 }
770 }
771
772 return( 0 );
773}
774
775/*
776 * Compare unsigned values
777 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200778int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000779{
Paul Bakker23986e52011-04-24 08:57:21 +0000780 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000781
Paul Bakker23986e52011-04-24 08:57:21 +0000782 for( i = X->n; i > 0; i-- )
783 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000784 break;
785
Paul Bakker23986e52011-04-24 08:57:21 +0000786 for( j = Y->n; j > 0; j-- )
787 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000788 break;
789
Paul Bakker23986e52011-04-24 08:57:21 +0000790 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000791 return( 0 );
792
793 if( i > j ) return( 1 );
794 if( j > i ) return( -1 );
795
Paul Bakker23986e52011-04-24 08:57:21 +0000796 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000797 {
Paul Bakker23986e52011-04-24 08:57:21 +0000798 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
799 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000800 }
801
802 return( 0 );
803}
804
805/*
806 * Compare signed values
807 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200808int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000809{
Paul Bakker23986e52011-04-24 08:57:21 +0000810 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000811
Paul Bakker23986e52011-04-24 08:57:21 +0000812 for( i = X->n; i > 0; i-- )
813 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000814 break;
815
Paul Bakker23986e52011-04-24 08:57:21 +0000816 for( j = Y->n; j > 0; j-- )
817 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000818 break;
819
Paul Bakker23986e52011-04-24 08:57:21 +0000820 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000821 return( 0 );
822
823 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000824 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000825
826 if( X->s > 0 && Y->s < 0 ) return( 1 );
827 if( Y->s > 0 && X->s < 0 ) return( -1 );
828
Paul Bakker23986e52011-04-24 08:57:21 +0000829 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000830 {
Paul Bakker23986e52011-04-24 08:57:21 +0000831 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
832 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000833 }
834
835 return( 0 );
836}
837
838/*
839 * Compare signed values
840 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200841int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000842{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200843 mbedtls_mpi Y;
844 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000845
846 *p = ( z < 0 ) ? -z : z;
847 Y.s = ( z < 0 ) ? -1 : 1;
848 Y.n = 1;
849 Y.p = p;
850
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200851 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000852}
853
854/*
855 * Unsigned addition: X = |A| + |B| (HAC 14.7)
856 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200857int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000858{
Paul Bakker23986e52011-04-24 08:57:21 +0000859 int ret;
860 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200861 mbedtls_mpi_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000862
863 if( X == B )
864 {
Janos Follath6cbacec2015-10-25 12:29:13 +0100865 if( B == A )
866 {
867 // Making a temporary copy instead of shifting by one to deny
868 // the possibility of corresponding side-channel attacks.
869 mbedtls_mpi TB;
Janos Follath044a86b2015-10-25 10:58:03 +0100870
Janos Follath6cbacec2015-10-25 12:29:13 +0100871 mbedtls_mpi_init( &TB );
872 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
873
874 return mbedtls_mpi_add_abs( X, A, &TB );
875 }
Janos Follath044a86b2015-10-25 10:58:03 +0100876
Janos Follath6cbacec2015-10-25 12:29:13 +0100877 B = A; A = X;
Paul Bakker5121ce52009-01-03 21:22:43 +0000878 }
879
880 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200881 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200882
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000883 /*
884 * X should always be positive as a result of unsigned additions.
885 */
886 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000887
Paul Bakker23986e52011-04-24 08:57:21 +0000888 for( j = B->n; j > 0; j-- )
889 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000890 break;
891
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200892 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000893
894 o = B->p; p = X->p; c = 0;
895
Paul Bakker23986e52011-04-24 08:57:21 +0000896 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000897 {
898 *p += c; c = ( *p < c );
899 *p += *o; c += ( *p < *o );
900 }
901
902 while( c != 0 )
903 {
904 if( i >= X->n )
905 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200906 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000907 p = X->p + i;
908 }
909
Paul Bakker2d319fd2012-09-16 21:34:26 +0000910 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000911 }
912
913cleanup:
914
915 return( ret );
916}
917
918/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000920 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200921static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000922{
Paul Bakker23986e52011-04-24 08:57:21 +0000923 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200924 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000925
926 for( i = c = 0; i < n; i++, s++, d++ )
927 {
928 z = ( *d < c ); *d -= c;
929 c = ( *d < *s ) + z; *d -= *s;
930 }
931
932 while( c != 0 )
933 {
934 z = ( *d < c ); *d -= c;
935 c = z; i++; d++;
936 }
937}
938
939/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100940 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000941 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200942int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000943{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200944 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000945 int ret;
946 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000947
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200948 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
949 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000950
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200951 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000952
953 if( X == B )
954 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200955 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000956 B = &TB;
957 }
958
959 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200960 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000961
Paul Bakker1ef7a532009-06-20 10:50:55 +0000962 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100963 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000964 */
965 X->s = 1;
966
Paul Bakker5121ce52009-01-03 21:22:43 +0000967 ret = 0;
968
Paul Bakker23986e52011-04-24 08:57:21 +0000969 for( n = B->n; n > 0; n-- )
970 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000971 break;
972
Paul Bakker23986e52011-04-24 08:57:21 +0000973 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000974
975cleanup:
976
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000978
979 return( ret );
980}
981
982/*
983 * Signed addition: X = A + B
984 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200985int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000986{
987 int ret, s = A->s;
988
989 if( A->s * B->s < 0 )
990 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200991 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000992 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200993 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000994 X->s = s;
995 }
996 else
997 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200998 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000999 X->s = -s;
1000 }
1001 }
1002 else
1003 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001004 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001005 X->s = s;
1006 }
1007
1008cleanup:
1009
1010 return( ret );
1011}
1012
1013/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001014 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001015 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001017{
1018 int ret, s = A->s;
1019
1020 if( A->s * B->s > 0 )
1021 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001022 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001023 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001024 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001025 X->s = s;
1026 }
1027 else
1028 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001029 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001030 X->s = -s;
1031 }
1032 }
1033 else
1034 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001035 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001036 X->s = s;
1037 }
1038
1039cleanup:
1040
1041 return( ret );
1042}
1043
1044/*
1045 * Signed addition: X = A + b
1046 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001047int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001048{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001049 mbedtls_mpi _B;
1050 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001051
1052 p[0] = ( b < 0 ) ? -b : b;
1053 _B.s = ( b < 0 ) ? -1 : 1;
1054 _B.n = 1;
1055 _B.p = p;
1056
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001057 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001058}
1059
1060/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001061 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001062 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001063int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001064{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001065 mbedtls_mpi _B;
1066 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001067
1068 p[0] = ( b < 0 ) ? -b : b;
1069 _B.s = ( b < 0 ) ? -1 : 1;
1070 _B.n = 1;
1071 _B.p = p;
1072
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001073 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001074}
1075
1076/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001077 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001078 */
1079static
1080#if defined(__APPLE__) && defined(__arm__)
1081/*
1082 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1083 * appears to need this to prevent bad ARM code generation at -O3.
1084 */
1085__attribute__ ((noinline))
1086#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001087void 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 +00001088{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001089 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001090
1091#if defined(MULADDC_HUIT)
1092 for( ; i >= 8; i -= 8 )
1093 {
1094 MULADDC_INIT
1095 MULADDC_HUIT
1096 MULADDC_STOP
1097 }
1098
1099 for( ; i > 0; i-- )
1100 {
1101 MULADDC_INIT
1102 MULADDC_CORE
1103 MULADDC_STOP
1104 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001105#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001106 for( ; i >= 16; i -= 16 )
1107 {
1108 MULADDC_INIT
1109 MULADDC_CORE MULADDC_CORE
1110 MULADDC_CORE MULADDC_CORE
1111 MULADDC_CORE MULADDC_CORE
1112 MULADDC_CORE MULADDC_CORE
1113
1114 MULADDC_CORE MULADDC_CORE
1115 MULADDC_CORE MULADDC_CORE
1116 MULADDC_CORE MULADDC_CORE
1117 MULADDC_CORE MULADDC_CORE
1118 MULADDC_STOP
1119 }
1120
1121 for( ; i >= 8; i -= 8 )
1122 {
1123 MULADDC_INIT
1124 MULADDC_CORE MULADDC_CORE
1125 MULADDC_CORE MULADDC_CORE
1126
1127 MULADDC_CORE MULADDC_CORE
1128 MULADDC_CORE MULADDC_CORE
1129 MULADDC_STOP
1130 }
1131
1132 for( ; i > 0; i-- )
1133 {
1134 MULADDC_INIT
1135 MULADDC_CORE
1136 MULADDC_STOP
1137 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001138#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001139
1140 t++;
1141
1142 do {
1143 *d += c; c = ( *d < c ); d++;
1144 }
1145 while( c != 0 );
1146}
1147
1148/*
1149 * Baseline multiplication: X = A * B (HAC 14.12)
1150 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001151int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001152{
Paul Bakker23986e52011-04-24 08:57:21 +00001153 int ret;
1154 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001155 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001156
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001157 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001158
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001159 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1160 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001161
Paul Bakker23986e52011-04-24 08:57:21 +00001162 for( i = A->n; i > 0; i-- )
1163 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001164 break;
1165
Paul Bakker23986e52011-04-24 08:57:21 +00001166 for( j = B->n; j > 0; j-- )
1167 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001168 break;
1169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001170 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1171 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001172
Paul Bakker23986e52011-04-24 08:57:21 +00001173 for( i++; j > 0; j-- )
1174 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001175
1176 X->s = A->s * B->s;
1177
1178cleanup:
1179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001180 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001181
1182 return( ret );
1183}
1184
1185/*
1186 * Baseline multiplication: X = A * b
1187 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001188int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001189{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001190 mbedtls_mpi _B;
1191 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001192
1193 _B.s = 1;
1194 _B.n = 1;
1195 _B.p = p;
1196 p[0] = b;
1197
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001198 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001199}
1200
1201/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001202 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001203 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001204int 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 +00001205{
Paul Bakker23986e52011-04-24 08:57:21 +00001206 int ret;
1207 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001208 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001210 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1211 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001212
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001213 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1214 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001215
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001216 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001217 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001218 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1219 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001220 return( 0 );
1221 }
1222
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001223 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1224 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001225 X.s = Y.s = 1;
1226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001227 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1228 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1229 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1230 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001231
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001232 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001233 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001234 {
1235 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001236 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1237 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001238 }
1239 else k = 0;
1240
1241 n = X.n - 1;
1242 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001243 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001244
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001245 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001246 {
1247 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001248 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001249 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001250 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001251
1252 for( i = n; i > t ; i-- )
1253 {
1254 if( X.p[i] >= Y.p[t] )
1255 Z.p[i - t - 1] = ~0;
1256 else
1257 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001258#if defined(MBEDTLS_HAVE_UDBL)
1259 mbedtls_t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001260
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001261 r = (mbedtls_t_udbl) X.p[i] << biL;
1262 r |= (mbedtls_t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001263 r /= Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001264 if( r > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1265 r = ( (mbedtls_t_udbl) 1 << biL ) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001267 Z.p[i - t - 1] = (mbedtls_mpi_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001268#else
1269 /*
1270 * __udiv_qrnnd_c, from gmp/longlong.h
1271 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001272 mbedtls_mpi_uint q0, q1, r0, r1;
1273 mbedtls_mpi_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001274
1275 d = Y.p[t];
1276 d0 = ( d << biH ) >> biH;
1277 d1 = ( d >> biH );
1278
1279 q1 = X.p[i] / d1;
1280 r1 = X.p[i] - d1 * q1;
1281 r1 <<= biH;
1282 r1 |= ( X.p[i - 1] >> biH );
1283
1284 m = q1 * d0;
1285 if( r1 < m )
1286 {
1287 q1--, r1 += d;
1288 while( r1 >= d && r1 < m )
1289 q1--, r1 += d;
1290 }
1291 r1 -= m;
1292
1293 q0 = r1 / d1;
1294 r0 = r1 - d1 * q0;
1295 r0 <<= biH;
1296 r0 |= ( X.p[i - 1] << biH ) >> biH;
1297
1298 m = q0 * d0;
1299 if( r0 < m )
1300 {
1301 q0--, r0 += d;
1302 while( r0 >= d && r0 < m )
1303 q0--, r0 += d;
1304 }
1305 r0 -= m;
1306
1307 Z.p[i - t - 1] = ( q1 << biH ) | q0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001308#endif /* MBEDTLS_HAVE_UDBL && !64-bit Apple with Clang 5.0 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001309 }
1310
1311 Z.p[i - t - 1]++;
1312 do
1313 {
1314 Z.p[i - t - 1]--;
1315
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001316 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001317 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001318 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001319 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001321 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001322 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1323 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001324 T2.p[2] = X.p[i];
1325 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001326 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001327
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001328 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1329 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1330 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001333 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001334 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1335 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1336 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001337 Z.p[i - t - 1]--;
1338 }
1339 }
1340
1341 if( Q != NULL )
1342 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001343 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001344 Q->s = A->s * B->s;
1345 }
1346
1347 if( R != NULL )
1348 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001349 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001350 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001351 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001352
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001353 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001354 R->s = 1;
1355 }
1356
1357cleanup:
1358
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001359 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1360 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001361
1362 return( ret );
1363}
1364
1365/*
1366 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001367 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001368int 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 +00001369{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001370 mbedtls_mpi _B;
1371 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001372
1373 p[0] = ( b < 0 ) ? -b : b;
1374 _B.s = ( b < 0 ) ? -1 : 1;
1375 _B.n = 1;
1376 _B.p = p;
1377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001378 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001379}
1380
1381/*
1382 * Modulo: R = A mod B
1383 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001384int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001385{
1386 int ret;
1387
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001388 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1389 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001390
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001393 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1394 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001396 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1397 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001398
1399cleanup:
1400
1401 return( ret );
1402}
1403
1404/*
1405 * Modulo: r = A mod b
1406 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001407int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001408{
Paul Bakker23986e52011-04-24 08:57:21 +00001409 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001410 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001411
1412 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001413 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001414
1415 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001416 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001417
1418 /*
1419 * handle trivial cases
1420 */
1421 if( b == 1 )
1422 {
1423 *r = 0;
1424 return( 0 );
1425 }
1426
1427 if( b == 2 )
1428 {
1429 *r = A->p[0] & 1;
1430 return( 0 );
1431 }
1432
1433 /*
1434 * general case
1435 */
Paul Bakker23986e52011-04-24 08:57:21 +00001436 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001437 {
Paul Bakker23986e52011-04-24 08:57:21 +00001438 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001439 y = ( y << biH ) | ( x >> biH );
1440 z = y / b;
1441 y -= z * b;
1442
1443 x <<= biH;
1444 y = ( y << biH ) | ( x >> biH );
1445 z = y / b;
1446 y -= z * b;
1447 }
1448
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001449 /*
1450 * If A is negative, then the current y represents a negative value.
1451 * Flipping it to the positive side.
1452 */
1453 if( A->s < 0 && y != 0 )
1454 y = b - y;
1455
Paul Bakker5121ce52009-01-03 21:22:43 +00001456 *r = y;
1457
1458 return( 0 );
1459}
1460
1461/*
1462 * Fast Montgomery initialization (thanks to Tom St Denis)
1463 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001464static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001465{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001467 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001468
1469 x = m0;
1470 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001471
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001472 for( i = biL; i >= 8; i /= 2 )
1473 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001474
1475 *mm = ~x + 1;
1476}
1477
1478/*
1479 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1480 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001481static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1482 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001483{
Paul Bakker23986e52011-04-24 08:57:21 +00001484 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001485 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001486
1487 memset( T->p, 0, T->n * ciL );
1488
1489 d = T->p;
1490 n = N->n;
1491 m = ( B->n < n ) ? B->n : n;
1492
1493 for( i = 0; i < n; i++ )
1494 {
1495 /*
1496 * T = (T + u0*B + u1*N) / 2^biL
1497 */
1498 u0 = A->p[i];
1499 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1500
1501 mpi_mul_hlp( m, B->p, d, u0 );
1502 mpi_mul_hlp( n, N->p, d, u1 );
1503
1504 *d++ = u0; d[n + 1] = 0;
1505 }
1506
Paul Bakker66d5d072014-06-17 16:39:18 +02001507 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001509 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001510 mpi_sub_hlp( n, N->p, A->p );
1511 else
1512 /* prevent timing attacks */
1513 mpi_sub_hlp( n, A->p, T->p );
1514}
1515
1516/*
1517 * Montgomery reduction: A = A * R^-1 mod N
1518 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001519static 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 +00001520{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001521 mbedtls_mpi_uint z = 1;
1522 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001523
Paul Bakker8ddb6452013-02-27 14:56:33 +01001524 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001525 U.p = &z;
1526
1527 mpi_montmul( A, &U, N, mm, T );
1528}
1529
1530/*
1531 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1532 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001533int 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 +00001534{
Paul Bakker23986e52011-04-24 08:57:21 +00001535 int ret;
1536 size_t wbits, wsize, one = 1;
1537 size_t i, j, nblimbs;
1538 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539 mbedtls_mpi_uint ei, mm, state;
1540 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001541 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001543 if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
1544 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001545
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001546 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1547 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001548
1549 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001550 * Init temps and window size
1551 */
1552 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001553 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1554 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001555 memset( W, 0, sizeof( W ) );
1556
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001557 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001558
1559 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1560 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1561
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001562 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1563 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001564
Paul Bakker5121ce52009-01-03 21:22:43 +00001565 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001566 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1567 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1568 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001569
1570 /*
Paul Bakker50546922012-05-19 08:40:49 +00001571 * Compensate for negative A (and correct at the end)
1572 */
1573 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001574 if( neg )
1575 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001576 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001577 Apos.s = 1;
1578 A = &Apos;
1579 }
1580
1581 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001582 * If 1st call, pre-compute R^2 mod N
1583 */
1584 if( _RR == NULL || _RR->p == NULL )
1585 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001586 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1587 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1588 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001589
1590 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001591 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001592 }
1593 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001594 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001595
1596 /*
1597 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1598 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001599 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1600 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001601 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001602 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001603
1604 mpi_montmul( &W[1], &RR, N, mm, &T );
1605
1606 /*
1607 * X = R^2 * R^-1 mod N = R mod N
1608 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001609 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001610 mpi_montred( X, N, mm, &T );
1611
1612 if( wsize > 1 )
1613 {
1614 /*
1615 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1616 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001617 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001619 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1620 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001621
1622 for( i = 0; i < wsize - 1; i++ )
1623 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001624
Paul Bakker5121ce52009-01-03 21:22:43 +00001625 /*
1626 * W[i] = W[i - 1] * W[1]
1627 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001628 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001629 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001630 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1631 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001632
1633 mpi_montmul( &W[i], &W[1], N, mm, &T );
1634 }
1635 }
1636
1637 nblimbs = E->n;
1638 bufsize = 0;
1639 nbits = 0;
1640 wbits = 0;
1641 state = 0;
1642
1643 while( 1 )
1644 {
1645 if( bufsize == 0 )
1646 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001647 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001648 break;
1649
Paul Bakker0d7702c2013-10-29 16:18:35 +01001650 nblimbs--;
1651
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001652 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001653 }
1654
1655 bufsize--;
1656
1657 ei = (E->p[nblimbs] >> bufsize) & 1;
1658
1659 /*
1660 * skip leading 0s
1661 */
1662 if( ei == 0 && state == 0 )
1663 continue;
1664
1665 if( ei == 0 && state == 1 )
1666 {
1667 /*
1668 * out of window, square X
1669 */
1670 mpi_montmul( X, X, N, mm, &T );
1671 continue;
1672 }
1673
1674 /*
1675 * add ei to current window
1676 */
1677 state = 2;
1678
1679 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001680 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001681
1682 if( nbits == wsize )
1683 {
1684 /*
1685 * X = X^wsize R^-1 mod N
1686 */
1687 for( i = 0; i < wsize; i++ )
1688 mpi_montmul( X, X, N, mm, &T );
1689
1690 /*
1691 * X = X * W[wbits] R^-1 mod N
1692 */
1693 mpi_montmul( X, &W[wbits], N, mm, &T );
1694
1695 state--;
1696 nbits = 0;
1697 wbits = 0;
1698 }
1699 }
1700
1701 /*
1702 * process the remaining bits
1703 */
1704 for( i = 0; i < nbits; i++ )
1705 {
1706 mpi_montmul( X, X, N, mm, &T );
1707
1708 wbits <<= 1;
1709
Paul Bakker66d5d072014-06-17 16:39:18 +02001710 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001711 mpi_montmul( X, &W[1], N, mm, &T );
1712 }
1713
1714 /*
1715 * X = A^E * R * R^-1 mod N = A^E mod N
1716 */
1717 mpi_montred( X, N, mm, &T );
1718
Paul Bakkerf6198c12012-05-16 08:02:29 +00001719 if( neg )
1720 {
1721 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001722 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001723 }
1724
Paul Bakker5121ce52009-01-03 21:22:43 +00001725cleanup:
1726
Paul Bakker66d5d072014-06-17 16:39:18 +02001727 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001728 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001729
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001730 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001731
Paul Bakker75a28602014-03-31 12:08:17 +02001732 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001733 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001734
1735 return( ret );
1736}
1737
Paul Bakker5121ce52009-01-03 21:22:43 +00001738/*
1739 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1740 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001741int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001742{
Paul Bakker23986e52011-04-24 08:57:21 +00001743 int ret;
1744 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001745 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001746
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001747 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001748
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001749 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1750 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001751
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001752 lz = mbedtls_mpi_lsb( &TA );
1753 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001754
Paul Bakker66d5d072014-06-17 16:39:18 +02001755 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001756 lz = lzt;
1757
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001758 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1759 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001760
Paul Bakker5121ce52009-01-03 21:22:43 +00001761 TA.s = TB.s = 1;
1762
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001763 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001764 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001765 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1766 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001767
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001768 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001769 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001770 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1771 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001772 }
1773 else
1774 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001775 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1776 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001777 }
1778 }
1779
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001780 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1781 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001782
1783cleanup:
1784
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001785 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001786
1787 return( ret );
1788}
1789
Paul Bakker33dc46b2014-04-30 16:11:39 +02001790/*
1791 * Fill X with size bytes of random.
1792 *
1793 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001794 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001795 * deterministic, eg for tests).
1796 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001797int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001798 int (*f_rng)(void *, unsigned char *, size_t),
1799 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001800{
Paul Bakker23986e52011-04-24 08:57:21 +00001801 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001802 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001803
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001804 if( size > MBEDTLS_MPI_MAX_SIZE )
1805 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001806
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001807 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1808 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001809
1810cleanup:
1811 return( ret );
1812}
1813
Paul Bakker5121ce52009-01-03 21:22:43 +00001814/*
1815 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1816 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001817int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001818{
1819 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001820 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001821
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001822 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 )
1823 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001824
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001825 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1826 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1827 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001828
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001829 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001830
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001831 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001832 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001833 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001834 goto cleanup;
1835 }
1836
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001837 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1838 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1839 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1840 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001841
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001842 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1843 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1844 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1845 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846
1847 do
1848 {
1849 while( ( TU.p[0] & 1 ) == 0 )
1850 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001851 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001852
1853 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1854 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001855 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1856 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001857 }
1858
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001859 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1860 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001861 }
1862
1863 while( ( TV.p[0] & 1 ) == 0 )
1864 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001865 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001866
1867 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1868 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001869 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1870 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001871 }
1872
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001873 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1874 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001875 }
1876
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001877 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001878 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1880 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1881 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001882 }
1883 else
1884 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001885 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1886 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1887 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001888 }
1889 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001890 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001891
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001892 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1893 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001894
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001895 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1896 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001897
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001898 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001899
1900cleanup:
1901
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001902 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1903 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1904 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001905
1906 return( ret );
1907}
1908
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001909#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001910
Paul Bakker5121ce52009-01-03 21:22:43 +00001911static const int small_prime[] =
1912{
1913 3, 5, 7, 11, 13, 17, 19, 23,
1914 29, 31, 37, 41, 43, 47, 53, 59,
1915 61, 67, 71, 73, 79, 83, 89, 97,
1916 101, 103, 107, 109, 113, 127, 131, 137,
1917 139, 149, 151, 157, 163, 167, 173, 179,
1918 181, 191, 193, 197, 199, 211, 223, 227,
1919 229, 233, 239, 241, 251, 257, 263, 269,
1920 271, 277, 281, 283, 293, 307, 311, 313,
1921 317, 331, 337, 347, 349, 353, 359, 367,
1922 373, 379, 383, 389, 397, 401, 409, 419,
1923 421, 431, 433, 439, 443, 449, 457, 461,
1924 463, 467, 479, 487, 491, 499, 503, 509,
1925 521, 523, 541, 547, 557, 563, 569, 571,
1926 577, 587, 593, 599, 601, 607, 613, 617,
1927 619, 631, 641, 643, 647, 653, 659, 661,
1928 673, 677, 683, 691, 701, 709, 719, 727,
1929 733, 739, 743, 751, 757, 761, 769, 773,
1930 787, 797, 809, 811, 821, 823, 827, 829,
1931 839, 853, 857, 859, 863, 877, 881, 883,
1932 887, 907, 911, 919, 929, 937, 941, 947,
1933 953, 967, 971, 977, 983, 991, 997, -103
1934};
1935
1936/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001937 * Small divisors test (X must be positive)
1938 *
1939 * Return values:
1940 * 0: no small factor (possible prime, more tests needed)
1941 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001942 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001943 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00001944 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001945static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00001946{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001947 int ret = 0;
1948 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001949 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001950
Paul Bakker5121ce52009-01-03 21:22:43 +00001951 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001952 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001953
1954 for( i = 0; small_prime[i] > 0; i++ )
1955 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001956 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001957 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001958
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001960
1961 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001962 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001963 }
1964
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001965cleanup:
1966 return( ret );
1967}
1968
1969/*
1970 * Miller-Rabin pseudo-primality test (HAC 4.24)
1971 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001972static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001973 int (*f_rng)(void *, unsigned char *, size_t),
1974 void *p_rng )
1975{
Pascal Junodb99183d2015-03-11 16:49:45 +01001976 int ret, count;
1977 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001978 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001979
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001980 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
1981 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001982
Paul Bakker5121ce52009-01-03 21:22:43 +00001983 /*
1984 * W = |X| - 1
1985 * R = W >> lsb( W )
1986 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001987 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
1988 s = mbedtls_mpi_lsb( &W );
1989 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
1990 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001991
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001992 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00001993 /*
1994 * HAC, table 4.4
1995 */
1996 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1997 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1998 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1999
2000 for( i = 0; i < n; i++ )
2001 {
2002 /*
2003 * pick a random A, 1 < A < |X| - 1
2004 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002005 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002006
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002007 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00002008 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002009 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002010 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00002011 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002012 A.p[0] |= 3;
2013
Pascal Junodb99183d2015-03-11 16:49:45 +01002014 count = 0;
2015 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002016 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002017
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002018 j = mbedtls_mpi_bitlen( &A );
2019 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002020 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002021 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002022 }
2023
2024 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002025 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002026 }
2027
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002028 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2029 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002030
2031 /*
2032 * A = A^R mod |X|
2033 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002035
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002036 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2037 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002038 continue;
2039
2040 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002041 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002042 {
2043 /*
2044 * A = A * A mod |X|
2045 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2047 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002048
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002050 break;
2051
2052 j++;
2053 }
2054
2055 /*
2056 * not prime if A != |X| - 1 or A == 1
2057 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2059 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002060 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002061 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002062 break;
2063 }
2064 }
2065
2066cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002067 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2068 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002069
2070 return( ret );
2071}
2072
2073/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002074 * Pseudo-primality test: small factors, then Miller-Rabin
2075 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002077 int (*f_rng)(void *, unsigned char *, size_t),
2078 void *p_rng )
2079{
2080 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002081 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002082
2083 XX.s = 1;
2084 XX.n = X->n;
2085 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002086
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002087 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2088 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2089 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002090
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002091 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002092 return( 0 );
2093
2094 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2095 {
2096 if( ret == 1 )
2097 return( 0 );
2098
2099 return( ret );
2100 }
2101
2102 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2103}
2104
2105/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002106 * Prime number generation
2107 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002108int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002109 int (*f_rng)(void *, unsigned char *, size_t),
2110 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002111{
Paul Bakker23986e52011-04-24 08:57:21 +00002112 int ret;
2113 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002114 mbedtls_mpi_uint r;
2115 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002116
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002117 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2118 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002120 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002121
2122 n = BITS_TO_LIMBS( nbits );
2123
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002124 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002125
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002126 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002127 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002128
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002129 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002130
2131 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002132
2133 if( dh_flag == 0 )
2134 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002135 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002136 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002137 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002138 goto cleanup;
2139
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002140 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002141 }
2142 }
2143 else
2144 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002145 /*
2146 * An necessary condition for Y and X = 2Y + 1 to be prime
2147 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2148 * Make sure it is satisfied, while keeping X = 3 mod 4
2149 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002150
2151 X->p[0] |= 2;
2152
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002153 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002154 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002155 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002156 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002157 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002158
2159 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2161 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002162
2163 while( 1 )
2164 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002165 /*
2166 * First, check small factors for X and Y
2167 * before doing Miller-Rabin on any of them
2168 */
2169 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2170 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2171 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2172 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002173 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002174 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002175 }
2176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002178 goto cleanup;
2179
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002180 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002181 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002182 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2183 * so up Y by 6 and X by 12.
2184 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002185 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2186 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002187 }
2188 }
2189
2190cleanup:
2191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002192 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002193
2194 return( ret );
2195}
2196
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002197#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002198
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002199#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002200
Paul Bakker23986e52011-04-24 08:57:21 +00002201#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002202
2203static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2204{
2205 { 693, 609, 21 },
2206 { 1764, 868, 28 },
2207 { 768454923, 542167814, 1 }
2208};
2209
Paul Bakker5121ce52009-01-03 21:22:43 +00002210/*
2211 * Checkup routine
2212 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002213int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002214{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002215 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002216 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002218 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2219 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002220
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002221 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002222 "EFE021C2645FD1DC586E69184AF4A31E" \
2223 "D5F53E93B5F123FA41680867BA110131" \
2224 "944FE7952E2517337780CB0DB80E61AA" \
2225 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002227 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002228 "B2E7EFD37075B9F03FF989C7C5051C20" \
2229 "34D2A323810251127E7BF8625A4F49A5" \
2230 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2231 "5B5C25763222FEFCCFC38B832366C29E" ) );
2232
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002233 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002234 "0066A198186C18C10B2F5ED9B522752A" \
2235 "9830B69916E535C8F047518A889A43A5" \
2236 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2237
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002238 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002239
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002240 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002241 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2242 "9E857EA95A03512E2BAE7391688D264A" \
2243 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2244 "8001B72E848A38CAE1C65F78E56ABDEF" \
2245 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2246 "ECF677152EF804370C1A305CAF3B5BF1" \
2247 "30879B56C61DE584A0F53A2447A51E" ) );
2248
2249 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002250 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002251
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002252 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002253 {
2254 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002255 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002256
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002257 ret = 1;
2258 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002259 }
2260
2261 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002262 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002265
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002266 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002267 "256567336059E52CAE22925474705F39A94" ) );
2268
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002269 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002270 "6613F26162223DF488E9CD48CC132C7A" \
2271 "0AC93C701B001B092E4E5B9F73BCD27B" \
2272 "9EE50D0657C77F374E903CDFA4C642" ) );
2273
2274 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002275 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002276
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002277 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2278 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002279 {
2280 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002281 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002282
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002283 ret = 1;
2284 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002285 }
2286
2287 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002289
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002290 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002291
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002292 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002293 "36E139AEA55215609D2816998ED020BB" \
2294 "BD96C37890F65171D948E9BC7CBAA4D9" \
2295 "325D24D6A3C12710F10A09FA08AB87" ) );
2296
2297 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002298 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002299
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002300 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002301 {
2302 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002303 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002304
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002305 ret = 1;
2306 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002307 }
2308
2309 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002310 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002311
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002312 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002313
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002314 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002315 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2316 "C3DBA76456363A10869622EAC2DD84EC" \
2317 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2318
2319 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002320 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002321
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002322 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002323 {
2324 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002325 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002326
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002327 ret = 1;
2328 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002329 }
2330
2331 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002332 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002333
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002334 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002336
Paul Bakker66d5d072014-06-17 16:39:18 +02002337 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002338 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002339 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2340 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002344 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002345 {
2346 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002348
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002349 ret = 1;
2350 goto cleanup;
2351 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002352 }
2353
2354 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002355 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002356
Paul Bakker5121ce52009-01-03 21:22:43 +00002357cleanup:
2358
2359 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002360 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002361
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002362 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2363 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002364
2365 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002366 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002367
2368 return( ret );
2369}
2370
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002371#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002372
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002373#endif /* MBEDTLS_BIGNUM_C */