blob: 280bbfd8542b859e5c3c5047a0bbdfe1cb9b8f5c [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>
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020041#include <limits.h>
Rich Evans00ab4702015-02-06 13:43:58 +000042
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020043#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000044#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020045#else
Rich Evans00ab4702015-02-06 13:43:58 +000046#include <stdio.h>
47#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020048#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020049#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020050#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020051#endif
52
Paul Bakker34617722014-06-13 17:20:13 +020053/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020055 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
56}
57
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000059#define biL (ciL << 3) /* bits in limb */
60#define biH (ciL << 2) /* half limb size */
61
62/*
63 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020064 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000065 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020066#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
67#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000068
69/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000070 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000071 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020072void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000073{
Paul Bakker6c591fa2011-05-05 11:49:20 +000074 if( X == NULL )
75 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000076
Paul Bakker6c591fa2011-05-05 11:49:20 +000077 X->s = 1;
78 X->n = 0;
79 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000080}
81
82/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000083 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000084 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020085void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000086{
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 if( X == NULL )
88 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000089
Paul Bakker6c591fa2011-05-05 11:49:20 +000090 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +000091 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020092 mbedtls_zeroize( X->p, X->n * ciL );
93 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +000094 }
95
Paul Bakker6c591fa2011-05-05 11:49:20 +000096 X->s = 1;
97 X->n = 0;
98 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000099}
100
101/*
102 * Enlarge to the specified number of limbs
103 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200104int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000105{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200106 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000107
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200108 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200109 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000110
Paul Bakker5121ce52009-01-03 21:22:43 +0000111 if( X->n < nblimbs )
112 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200113 if( ( p = mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200114 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000115
Paul Bakker5121ce52009-01-03 21:22:43 +0000116 if( X->p != NULL )
117 {
118 memcpy( p, X->p, X->n * ciL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119 mbedtls_zeroize( X->p, X->n * ciL );
120 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000121 }
122
123 X->n = nblimbs;
124 X->p = p;
125 }
126
127 return( 0 );
128}
129
130/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100131 * Resize down as much as possible,
132 * while keeping at least the specified number of limbs
133 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100135{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100137 size_t i;
138
139 /* Actually resize up in this case */
140 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200141 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100142
143 for( i = X->n - 1; i > 0; i-- )
144 if( X->p[i] != 0 )
145 break;
146 i++;
147
148 if( i < nblimbs )
149 i = nblimbs;
150
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200151 if( ( p = mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200152 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100153
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154 if( X->p != NULL )
155 {
156 memcpy( p, X->p, i * ciL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 mbedtls_zeroize( X->p, X->n * ciL );
158 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100159 }
160
161 X->n = i;
162 X->p = p;
163
164 return( 0 );
165}
166
167/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000168 * Copy the contents of Y into X
169 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000171{
Paul Bakker23986e52011-04-24 08:57:21 +0000172 int ret;
173 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000174
175 if( X == Y )
176 return( 0 );
177
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200178 if( Y->p == NULL )
179 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200181 return( 0 );
182 }
183
Paul Bakker5121ce52009-01-03 21:22:43 +0000184 for( i = Y->n - 1; i > 0; i-- )
185 if( Y->p[i] != 0 )
186 break;
187 i++;
188
189 X->s = Y->s;
190
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000192
193 memset( X->p, 0, X->n * ciL );
194 memcpy( X->p, Y->p, i * ciL );
195
196cleanup:
197
198 return( ret );
199}
200
201/*
202 * Swap the contents of X and Y
203 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200204void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000205{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000207
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200208 memcpy( &T, X, sizeof( mbedtls_mpi ) );
209 memcpy( X, Y, sizeof( mbedtls_mpi ) );
210 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000211}
212
213/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100214 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100215 * about whether the assignment was made or not.
216 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100217 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100219{
220 int ret = 0;
221 size_t i;
222
Pascal Junodb99183d2015-03-11 16:49:45 +0100223 /* make sure assign is 0 or 1 in a time-constant manner */
224 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100225
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200226 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100227
Paul Bakker66d5d072014-06-17 16:39:18 +0200228 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100229
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100230 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200231 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100232
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100233 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200234 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100235
236cleanup:
237 return( ret );
238}
239
240/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100241 * Conditionally swap X and Y, without leaking information
242 * about whether the swap was made or not.
243 * Here it is not ok to simply swap the pointers, which whould lead to
244 * different memory access patterns when X and Y are used afterwards.
245 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200246int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100247{
248 int ret, s;
249 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250 mbedtls_mpi_uint tmp;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100251
252 if( X == Y )
253 return( 0 );
254
Pascal Junodb99183d2015-03-11 16:49:45 +0100255 /* make sure swap is 0 or 1 in a time-constant manner */
256 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100257
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200258 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
259 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100260
261 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200262 X->s = X->s * ( 1 - swap ) + Y->s * swap;
263 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100264
265
266 for( i = 0; i < X->n; i++ )
267 {
268 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200269 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
270 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100271 }
272
273cleanup:
274 return( ret );
275}
276
277/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000278 * Set value from integer
279 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200280int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000281{
282 int ret;
283
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000285 memset( X->p, 0, X->n * ciL );
286
287 X->p[0] = ( z < 0 ) ? -z : z;
288 X->s = ( z < 0 ) ? -1 : 1;
289
290cleanup:
291
292 return( ret );
293}
294
295/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000296 * Get a specific bit
297 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200298int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000299{
300 if( X->n * biL <= pos )
301 return( 0 );
302
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200303 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000304}
305
306/*
307 * Set a bit to a specific value of 0 or 1
308 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200309int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000310{
311 int ret = 0;
312 size_t off = pos / biL;
313 size_t idx = pos % biL;
314
315 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200316 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200317
Paul Bakker2f5947e2011-05-18 15:47:11 +0000318 if( X->n * biL <= pos )
319 {
320 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200321 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000322
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200323 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000324 }
325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
327 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000328
329cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200330
Paul Bakker2f5947e2011-05-18 15:47:11 +0000331 return( ret );
332}
333
334/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200335 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000336 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200337size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000338{
Paul Bakker23986e52011-04-24 08:57:21 +0000339 size_t i, j, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000340
341 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000342 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000343 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
344 return( count );
345
346 return( 0 );
347}
348
349/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200350 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000351 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200352size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000353{
Paul Bakker23986e52011-04-24 08:57:21 +0000354 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000355
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200356 if( X->n == 0 )
357 return( 0 );
358
Paul Bakker5121ce52009-01-03 21:22:43 +0000359 for( i = X->n - 1; i > 0; i-- )
360 if( X->p[i] != 0 )
361 break;
362
Paul Bakker23986e52011-04-24 08:57:21 +0000363 for( j = biL; j > 0; j-- )
364 if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000365 break;
366
Paul Bakker23986e52011-04-24 08:57:21 +0000367 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000368}
369
370/*
371 * Return the total size in bytes
372 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200373size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000374{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200375 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000376}
377
378/*
379 * Convert an ASCII character to digit value
380 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000382{
383 *d = 255;
384
385 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
386 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
387 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389 if( *d >= (mbedtls_mpi_uint) radix )
390 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000391
392 return( 0 );
393}
394
395/*
396 * Import from an ASCII string
397 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000399{
Paul Bakker23986e52011-04-24 08:57:21 +0000400 int ret;
401 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200402 mbedtls_mpi_uint d;
403 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000404
405 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000409
Paul Bakkerff60ee62010-03-16 21:09:09 +0000410 slen = strlen( s );
411
Paul Bakker5121ce52009-01-03 21:22:43 +0000412 if( radix == 16 )
413 {
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200414 if( slen > SIZE_T_MAX >> 2 )
415 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
416
Paul Bakkerff60ee62010-03-16 21:09:09 +0000417 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000418
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
420 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000421
Paul Bakker23986e52011-04-24 08:57:21 +0000422 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000423 {
Paul Bakker23986e52011-04-24 08:57:21 +0000424 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000425 {
426 X->s = -1;
427 break;
428 }
429
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200430 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200431 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000432 }
433 }
434 else
435 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200436 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000437
Paul Bakkerff60ee62010-03-16 21:09:09 +0000438 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000439 {
440 if( i == 0 && s[i] == '-' )
441 {
442 X->s = -1;
443 continue;
444 }
445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
447 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000448
449 if( X->s == 1 )
450 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200451 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000452 }
453 else
454 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000456 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000457 }
458 }
459
460cleanup:
461
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000463
464 return( ret );
465}
466
467/*
468 * Helper to write the digits high-order first
469 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000471{
472 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200473 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000474
475 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000477
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200478 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
479 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
482 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
484 if( r < 10 )
485 *(*p)++ = (char)( r + 0x30 );
486 else
487 *(*p)++ = (char)( r + 0x37 );
488
489cleanup:
490
491 return( ret );
492}
493
494/*
495 * Export into an ASCII string
496 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100497int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
498 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000499{
Paul Bakker23986e52011-04-24 08:57:21 +0000500 int ret = 0;
501 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000502 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000504
505 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200506 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000507
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200508 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000509 if( radix >= 4 ) n >>= 1;
510 if( radix >= 16 ) n >>= 1;
511 n += 3;
512
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100513 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000514 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100515 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000517 }
518
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100519 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000521
522 if( X->s == -1 )
523 *p++ = '-';
524
525 if( radix == 16 )
526 {
Paul Bakker23986e52011-04-24 08:57:21 +0000527 int c;
528 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000529
Paul Bakker23986e52011-04-24 08:57:21 +0000530 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000531 {
Paul Bakker23986e52011-04-24 08:57:21 +0000532 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000533 {
Paul Bakker23986e52011-04-24 08:57:21 +0000534 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000535
Paul Bakker6c343d72014-07-10 14:36:19 +0200536 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000537 continue;
538
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000539 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000540 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000541 k = 1;
542 }
543 }
544 }
545 else
546 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200547 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000548
549 if( T.s == -1 )
550 T.s = 1;
551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200552 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000553 }
554
555 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100556 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000557
558cleanup:
559
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200560 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000561
562 return( ret );
563}
564
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000566/*
567 * Read X from an opened file
568 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200569int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000570{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200571 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000572 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000573 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000574 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000575 * Buffer should have space for (short) label and decimal formatted MPI,
576 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000577 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000579
580 memset( s, 0, sizeof( s ) );
581 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200582 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000583
584 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000585 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000587
Paul Bakker5121ce52009-01-03 21:22:43 +0000588 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
589 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
590
591 p = s + slen;
592 while( --p >= s )
593 if( mpi_get_digit( &d, radix, *p ) != 0 )
594 break;
595
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200596 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000597}
598
599/*
600 * Write X into an opened file (or stdout if fout == NULL)
601 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000603{
Paul Bakker23986e52011-04-24 08:57:21 +0000604 int ret;
605 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000606 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000607 * Buffer should have space for (short) label and decimal formatted MPI,
608 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000609 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200610 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000611
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100612 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000613
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100614 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000615
616 if( p == NULL ) p = "";
617
618 plen = strlen( p );
619 slen = strlen( s );
620 s[slen++] = '\r';
621 s[slen++] = '\n';
622
623 if( fout != NULL )
624 {
625 if( fwrite( p, 1, plen, fout ) != plen ||
626 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200627 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000628 }
629 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000631
632cleanup:
633
634 return( ret );
635}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200636#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000637
638/*
639 * Import X from unsigned binary data, big endian
640 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000642{
Paul Bakker23986e52011-04-24 08:57:21 +0000643 int ret;
644 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000645
646 for( n = 0; n < buflen; n++ )
647 if( buf[n] != 0 )
648 break;
649
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
651 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000652
Paul Bakker23986e52011-04-24 08:57:21 +0000653 for( i = buflen, j = 0; i > n; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200654 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000655
656cleanup:
657
658 return( ret );
659}
660
661/*
662 * Export X into unsigned binary data, big endian
663 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200664int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000665{
Paul Bakker23986e52011-04-24 08:57:21 +0000666 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000667
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200668 n = mbedtls_mpi_size( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000669
670 if( buflen < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000672
673 memset( buf, 0, buflen );
674
675 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
676 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
677
678 return( 0 );
679}
680
681/*
682 * Left-shift: X <<= count
683 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000685{
Paul Bakker23986e52011-04-24 08:57:21 +0000686 int ret;
687 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200688 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000689
690 v0 = count / (biL );
691 t1 = count & (biL - 1);
692
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200693 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000694
Paul Bakkerf9688572011-05-05 10:00:45 +0000695 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000697
698 ret = 0;
699
700 /*
701 * shift by count / limb_size
702 */
703 if( v0 > 0 )
704 {
Paul Bakker23986e52011-04-24 08:57:21 +0000705 for( i = X->n; i > v0; i-- )
706 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
Paul Bakker23986e52011-04-24 08:57:21 +0000708 for( ; i > 0; i-- )
709 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000710 }
711
712 /*
713 * shift by count % limb_size
714 */
715 if( t1 > 0 )
716 {
717 for( i = v0; i < X->n; i++ )
718 {
719 r1 = X->p[i] >> (biL - t1);
720 X->p[i] <<= t1;
721 X->p[i] |= r0;
722 r0 = r1;
723 }
724 }
725
726cleanup:
727
728 return( ret );
729}
730
731/*
732 * Right-shift: X >>= count
733 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200734int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000735{
Paul Bakker23986e52011-04-24 08:57:21 +0000736 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737 mbedtls_mpi_uint r0 = 0, r1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000738
739 v0 = count / biL;
740 v1 = count & (biL - 1);
741
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100742 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100744
Paul Bakker5121ce52009-01-03 21:22:43 +0000745 /*
746 * shift by count / limb_size
747 */
748 if( v0 > 0 )
749 {
750 for( i = 0; i < X->n - v0; i++ )
751 X->p[i] = X->p[i + v0];
752
753 for( ; i < X->n; i++ )
754 X->p[i] = 0;
755 }
756
757 /*
758 * shift by count % limb_size
759 */
760 if( v1 > 0 )
761 {
Paul Bakker23986e52011-04-24 08:57:21 +0000762 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000763 {
Paul Bakker23986e52011-04-24 08:57:21 +0000764 r1 = X->p[i - 1] << (biL - v1);
765 X->p[i - 1] >>= v1;
766 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000767 r0 = r1;
768 }
769 }
770
771 return( 0 );
772}
773
774/*
775 * Compare unsigned values
776 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200777int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000778{
Paul Bakker23986e52011-04-24 08:57:21 +0000779 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000780
Paul Bakker23986e52011-04-24 08:57:21 +0000781 for( i = X->n; i > 0; i-- )
782 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000783 break;
784
Paul Bakker23986e52011-04-24 08:57:21 +0000785 for( j = Y->n; j > 0; j-- )
786 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000787 break;
788
Paul Bakker23986e52011-04-24 08:57:21 +0000789 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000790 return( 0 );
791
792 if( i > j ) return( 1 );
793 if( j > i ) return( -1 );
794
Paul Bakker23986e52011-04-24 08:57:21 +0000795 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000796 {
Paul Bakker23986e52011-04-24 08:57:21 +0000797 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
798 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000799 }
800
801 return( 0 );
802}
803
804/*
805 * Compare signed values
806 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200807int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000808{
Paul Bakker23986e52011-04-24 08:57:21 +0000809 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000810
Paul Bakker23986e52011-04-24 08:57:21 +0000811 for( i = X->n; i > 0; i-- )
812 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000813 break;
814
Paul Bakker23986e52011-04-24 08:57:21 +0000815 for( j = Y->n; j > 0; j-- )
816 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000817 break;
818
Paul Bakker23986e52011-04-24 08:57:21 +0000819 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000820 return( 0 );
821
822 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000823 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000824
825 if( X->s > 0 && Y->s < 0 ) return( 1 );
826 if( Y->s > 0 && X->s < 0 ) return( -1 );
827
Paul Bakker23986e52011-04-24 08:57:21 +0000828 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000829 {
Paul Bakker23986e52011-04-24 08:57:21 +0000830 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
831 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000832 }
833
834 return( 0 );
835}
836
837/*
838 * Compare signed values
839 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200840int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000841{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200842 mbedtls_mpi Y;
843 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000844
845 *p = ( z < 0 ) ? -z : z;
846 Y.s = ( z < 0 ) ? -1 : 1;
847 Y.n = 1;
848 Y.p = p;
849
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200850 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000851}
852
853/*
854 * Unsigned addition: X = |A| + |B| (HAC 14.7)
855 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200856int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000857{
Paul Bakker23986e52011-04-24 08:57:21 +0000858 int ret;
859 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200860 mbedtls_mpi_uint *o, *p, c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000861
862 if( X == B )
863 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200864 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000865 }
866
867 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200868 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200869
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000870 /*
871 * X should always be positive as a result of unsigned additions.
872 */
873 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000874
Paul Bakker23986e52011-04-24 08:57:21 +0000875 for( j = B->n; j > 0; j-- )
876 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000877 break;
878
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200879 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000880
881 o = B->p; p = X->p; c = 0;
882
Paul Bakker23986e52011-04-24 08:57:21 +0000883 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000884 {
885 *p += c; c = ( *p < c );
886 *p += *o; c += ( *p < *o );
887 }
888
889 while( c != 0 )
890 {
891 if( i >= X->n )
892 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200893 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000894 p = X->p + i;
895 }
896
Paul Bakker2d319fd2012-09-16 21:34:26 +0000897 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000898 }
899
900cleanup:
901
902 return( ret );
903}
904
905/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200906 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +0000907 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200908static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +0000909{
Paul Bakker23986e52011-04-24 08:57:21 +0000910 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200911 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000912
913 for( i = c = 0; i < n; i++, s++, d++ )
914 {
915 z = ( *d < c ); *d -= c;
916 c = ( *d < *s ) + z; *d -= *s;
917 }
918
919 while( c != 0 )
920 {
921 z = ( *d < c ); *d -= c;
922 c = z; i++; d++;
923 }
924}
925
926/*
Paul Bakker60b1d102013-10-29 10:02:51 +0100927 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +0000928 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200929int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000930{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200931 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +0000932 int ret;
933 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000934
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200935 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
936 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000937
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200938 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000939
940 if( X == B )
941 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200942 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000943 B = &TB;
944 }
945
946 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000948
Paul Bakker1ef7a532009-06-20 10:50:55 +0000949 /*
Paul Bakker60b1d102013-10-29 10:02:51 +0100950 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +0000951 */
952 X->s = 1;
953
Paul Bakker5121ce52009-01-03 21:22:43 +0000954 ret = 0;
955
Paul Bakker23986e52011-04-24 08:57:21 +0000956 for( n = B->n; n > 0; n-- )
957 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000958 break;
959
Paul Bakker23986e52011-04-24 08:57:21 +0000960 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000961
962cleanup:
963
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200964 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +0000965
966 return( ret );
967}
968
969/*
970 * Signed addition: X = A + B
971 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200972int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000973{
974 int ret, s = A->s;
975
976 if( A->s * B->s < 0 )
977 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200978 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000979 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200980 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000981 X->s = s;
982 }
983 else
984 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200985 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000986 X->s = -s;
987 }
988 }
989 else
990 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200991 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000992 X->s = s;
993 }
994
995cleanup:
996
997 return( ret );
998}
999
1000/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001001 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001002 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001003int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001004{
1005 int ret, s = A->s;
1006
1007 if( A->s * B->s > 0 )
1008 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001009 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001010 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001011 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001012 X->s = s;
1013 }
1014 else
1015 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001017 X->s = -s;
1018 }
1019 }
1020 else
1021 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001022 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001023 X->s = s;
1024 }
1025
1026cleanup:
1027
1028 return( ret );
1029}
1030
1031/*
1032 * Signed addition: X = A + b
1033 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001034int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001035{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001036 mbedtls_mpi _B;
1037 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001038
1039 p[0] = ( b < 0 ) ? -b : b;
1040 _B.s = ( b < 0 ) ? -1 : 1;
1041 _B.n = 1;
1042 _B.p = p;
1043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001044 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001045}
1046
1047/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001048 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001049 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001051{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001052 mbedtls_mpi _B;
1053 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001054
1055 p[0] = ( b < 0 ) ? -b : b;
1056 _B.s = ( b < 0 ) ? -1 : 1;
1057 _B.n = 1;
1058 _B.p = p;
1059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001060 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001061}
1062
1063/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001064 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001065 */
1066static
1067#if defined(__APPLE__) && defined(__arm__)
1068/*
1069 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1070 * appears to need this to prevent bad ARM code generation at -O3.
1071 */
1072__attribute__ ((noinline))
1073#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001074void 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 +00001075{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001076 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001077
1078#if defined(MULADDC_HUIT)
1079 for( ; i >= 8; i -= 8 )
1080 {
1081 MULADDC_INIT
1082 MULADDC_HUIT
1083 MULADDC_STOP
1084 }
1085
1086 for( ; i > 0; i-- )
1087 {
1088 MULADDC_INIT
1089 MULADDC_CORE
1090 MULADDC_STOP
1091 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001092#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001093 for( ; i >= 16; i -= 16 )
1094 {
1095 MULADDC_INIT
1096 MULADDC_CORE MULADDC_CORE
1097 MULADDC_CORE MULADDC_CORE
1098 MULADDC_CORE MULADDC_CORE
1099 MULADDC_CORE MULADDC_CORE
1100
1101 MULADDC_CORE MULADDC_CORE
1102 MULADDC_CORE MULADDC_CORE
1103 MULADDC_CORE MULADDC_CORE
1104 MULADDC_CORE MULADDC_CORE
1105 MULADDC_STOP
1106 }
1107
1108 for( ; i >= 8; i -= 8 )
1109 {
1110 MULADDC_INIT
1111 MULADDC_CORE MULADDC_CORE
1112 MULADDC_CORE MULADDC_CORE
1113
1114 MULADDC_CORE MULADDC_CORE
1115 MULADDC_CORE MULADDC_CORE
1116 MULADDC_STOP
1117 }
1118
1119 for( ; i > 0; i-- )
1120 {
1121 MULADDC_INIT
1122 MULADDC_CORE
1123 MULADDC_STOP
1124 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001125#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001126
1127 t++;
1128
1129 do {
1130 *d += c; c = ( *d < c ); d++;
1131 }
1132 while( c != 0 );
1133}
1134
1135/*
1136 * Baseline multiplication: X = A * B (HAC 14.12)
1137 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001138int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001139{
Paul Bakker23986e52011-04-24 08:57:21 +00001140 int ret;
1141 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001142 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001143
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001144 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001145
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001146 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1147 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001148
Paul Bakker23986e52011-04-24 08:57:21 +00001149 for( i = A->n; i > 0; i-- )
1150 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001151 break;
1152
Paul Bakker23986e52011-04-24 08:57:21 +00001153 for( j = B->n; j > 0; j-- )
1154 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001155 break;
1156
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001157 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1158 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001159
Paul Bakker23986e52011-04-24 08:57:21 +00001160 for( i++; j > 0; j-- )
1161 mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001162
1163 X->s = A->s * B->s;
1164
1165cleanup:
1166
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001167 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001168
1169 return( ret );
1170}
1171
1172/*
1173 * Baseline multiplication: X = A * b
1174 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001175int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001176{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001177 mbedtls_mpi _B;
1178 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001179
1180 _B.s = 1;
1181 _B.n = 1;
1182 _B.p = p;
1183 p[0] = b;
1184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001185 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001186}
1187
1188/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001189 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001190 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001191int 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 +00001192{
Paul Bakker23986e52011-04-24 08:57:21 +00001193 int ret;
1194 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001195 mbedtls_mpi X, Y, Z, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001196
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001197 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1198 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001199
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001200 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1201 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001202
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001203 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001204 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001205 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1206 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001207 return( 0 );
1208 }
1209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001210 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1211 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001212 X.s = Y.s = 1;
1213
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001214 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1215 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1216 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1217 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001218
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001219 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001220 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001221 {
1222 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001223 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1224 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001225 }
1226 else k = 0;
1227
1228 n = X.n - 1;
1229 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001230 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001231
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001232 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001233 {
1234 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001235 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001236 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001237 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001238
1239 for( i = n; i > t ; i-- )
1240 {
1241 if( X.p[i] >= Y.p[t] )
1242 Z.p[i - t - 1] = ~0;
1243 else
1244 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001245#if defined(MBEDTLS_HAVE_UDBL)
1246 mbedtls_t_udbl r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001247
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001248 r = (mbedtls_t_udbl) X.p[i] << biL;
1249 r |= (mbedtls_t_udbl) X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001250 r /= Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001251 if( r > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1252 r = ( (mbedtls_t_udbl) 1 << biL ) - 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001253
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001254 Z.p[i - t - 1] = (mbedtls_mpi_uint) r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001255#else
1256 /*
1257 * __udiv_qrnnd_c, from gmp/longlong.h
1258 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001259 mbedtls_mpi_uint q0, q1, r0, r1;
1260 mbedtls_mpi_uint d0, d1, d, m;
Paul Bakker5121ce52009-01-03 21:22:43 +00001261
1262 d = Y.p[t];
1263 d0 = ( d << biH ) >> biH;
1264 d1 = ( d >> biH );
1265
1266 q1 = X.p[i] / d1;
1267 r1 = X.p[i] - d1 * q1;
1268 r1 <<= biH;
1269 r1 |= ( X.p[i - 1] >> biH );
1270
1271 m = q1 * d0;
1272 if( r1 < m )
1273 {
1274 q1--, r1 += d;
1275 while( r1 >= d && r1 < m )
1276 q1--, r1 += d;
1277 }
1278 r1 -= m;
1279
1280 q0 = r1 / d1;
1281 r0 = r1 - d1 * q0;
1282 r0 <<= biH;
1283 r0 |= ( X.p[i - 1] << biH ) >> biH;
1284
1285 m = q0 * d0;
1286 if( r0 < m )
1287 {
1288 q0--, r0 += d;
1289 while( r0 >= d && r0 < m )
1290 q0--, r0 += d;
1291 }
1292 r0 -= m;
1293
1294 Z.p[i - t - 1] = ( q1 << biH ) | q0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001295#endif /* MBEDTLS_HAVE_UDBL && !64-bit Apple with Clang 5.0 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001296 }
1297
1298 Z.p[i - t - 1]++;
1299 do
1300 {
1301 Z.p[i - t - 1]--;
1302
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001303 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001304 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001305 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001306 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001307
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001308 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001309 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1310 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001311 T2.p[2] = X.p[i];
1312 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001313 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001314
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001315 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1316 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1317 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001319 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001320 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001321 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1322 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1323 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001324 Z.p[i - t - 1]--;
1325 }
1326 }
1327
1328 if( Q != NULL )
1329 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001330 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001331 Q->s = A->s * B->s;
1332 }
1333
1334 if( R != NULL )
1335 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001337 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001338 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001340 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001341 R->s = 1;
1342 }
1343
1344cleanup:
1345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001346 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1347 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001348
1349 return( ret );
1350}
1351
1352/*
1353 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001354 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001355int 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 +00001356{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001357 mbedtls_mpi _B;
1358 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001359
1360 p[0] = ( b < 0 ) ? -b : b;
1361 _B.s = ( b < 0 ) ? -1 : 1;
1362 _B.n = 1;
1363 _B.p = p;
1364
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001366}
1367
1368/*
1369 * Modulo: R = A mod B
1370 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001371int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001372{
1373 int ret;
1374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001375 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1376 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001378 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001379
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001380 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1381 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001383 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1384 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001385
1386cleanup:
1387
1388 return( ret );
1389}
1390
1391/*
1392 * Modulo: r = A mod b
1393 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001394int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001395{
Paul Bakker23986e52011-04-24 08:57:21 +00001396 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001397 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001398
1399 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001401
1402 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001404
1405 /*
1406 * handle trivial cases
1407 */
1408 if( b == 1 )
1409 {
1410 *r = 0;
1411 return( 0 );
1412 }
1413
1414 if( b == 2 )
1415 {
1416 *r = A->p[0] & 1;
1417 return( 0 );
1418 }
1419
1420 /*
1421 * general case
1422 */
Paul Bakker23986e52011-04-24 08:57:21 +00001423 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001424 {
Paul Bakker23986e52011-04-24 08:57:21 +00001425 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001426 y = ( y << biH ) | ( x >> biH );
1427 z = y / b;
1428 y -= z * b;
1429
1430 x <<= biH;
1431 y = ( y << biH ) | ( x >> biH );
1432 z = y / b;
1433 y -= z * b;
1434 }
1435
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001436 /*
1437 * If A is negative, then the current y represents a negative value.
1438 * Flipping it to the positive side.
1439 */
1440 if( A->s < 0 && y != 0 )
1441 y = b - y;
1442
Paul Bakker5121ce52009-01-03 21:22:43 +00001443 *r = y;
1444
1445 return( 0 );
1446}
1447
1448/*
1449 * Fast Montgomery initialization (thanks to Tom St Denis)
1450 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001451static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001452{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001453 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001454 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001455
1456 x = m0;
1457 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001458
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001459 for( i = biL; i >= 8; i /= 2 )
1460 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001461
1462 *mm = ~x + 1;
1463}
1464
1465/*
1466 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1467 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001468static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1469 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001470{
Paul Bakker23986e52011-04-24 08:57:21 +00001471 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001472 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001473
1474 memset( T->p, 0, T->n * ciL );
1475
1476 d = T->p;
1477 n = N->n;
1478 m = ( B->n < n ) ? B->n : n;
1479
1480 for( i = 0; i < n; i++ )
1481 {
1482 /*
1483 * T = (T + u0*B + u1*N) / 2^biL
1484 */
1485 u0 = A->p[i];
1486 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1487
1488 mpi_mul_hlp( m, B->p, d, u0 );
1489 mpi_mul_hlp( n, N->p, d, u1 );
1490
1491 *d++ = u0; d[n + 1] = 0;
1492 }
1493
Paul Bakker66d5d072014-06-17 16:39:18 +02001494 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001496 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001497 mpi_sub_hlp( n, N->p, A->p );
1498 else
1499 /* prevent timing attacks */
1500 mpi_sub_hlp( n, A->p, T->p );
1501}
1502
1503/*
1504 * Montgomery reduction: A = A * R^-1 mod N
1505 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506static 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 +00001507{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001508 mbedtls_mpi_uint z = 1;
1509 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001510
Paul Bakker8ddb6452013-02-27 14:56:33 +01001511 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001512 U.p = &z;
1513
1514 mpi_montmul( A, &U, N, mm, T );
1515}
1516
1517/*
1518 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1519 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001520int 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 +00001521{
Paul Bakker23986e52011-04-24 08:57:21 +00001522 int ret;
1523 size_t wbits, wsize, one = 1;
1524 size_t i, j, nblimbs;
1525 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001526 mbedtls_mpi_uint ei, mm, state;
1527 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001528 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001529
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001530 if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
1531 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001532
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001533 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1534 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001535
1536 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001537 * Init temps and window size
1538 */
1539 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001540 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1541 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001542 memset( W, 0, sizeof( W ) );
1543
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001544 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001545
1546 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1547 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1548
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001549 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1550 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001551
Paul Bakker5121ce52009-01-03 21:22:43 +00001552 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001553 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1554 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1555 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001556
1557 /*
Paul Bakker50546922012-05-19 08:40:49 +00001558 * Compensate for negative A (and correct at the end)
1559 */
1560 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001561 if( neg )
1562 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001563 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001564 Apos.s = 1;
1565 A = &Apos;
1566 }
1567
1568 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001569 * If 1st call, pre-compute R^2 mod N
1570 */
1571 if( _RR == NULL || _RR->p == NULL )
1572 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001573 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1574 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1575 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001576
1577 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001578 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001579 }
1580 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001581 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001582
1583 /*
1584 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1585 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001586 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1587 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001588 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001589 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001590
1591 mpi_montmul( &W[1], &RR, N, mm, &T );
1592
1593 /*
1594 * X = R^2 * R^-1 mod N = R mod N
1595 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001596 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001597 mpi_montred( X, N, mm, &T );
1598
1599 if( wsize > 1 )
1600 {
1601 /*
1602 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1603 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001604 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001605
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001606 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1607 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001608
1609 for( i = 0; i < wsize - 1; i++ )
1610 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001611
Paul Bakker5121ce52009-01-03 21:22:43 +00001612 /*
1613 * W[i] = W[i - 1] * W[1]
1614 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001615 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001616 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001617 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1618 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001619
1620 mpi_montmul( &W[i], &W[1], N, mm, &T );
1621 }
1622 }
1623
1624 nblimbs = E->n;
1625 bufsize = 0;
1626 nbits = 0;
1627 wbits = 0;
1628 state = 0;
1629
1630 while( 1 )
1631 {
1632 if( bufsize == 0 )
1633 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001634 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001635 break;
1636
Paul Bakker0d7702c2013-10-29 16:18:35 +01001637 nblimbs--;
1638
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001639 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001640 }
1641
1642 bufsize--;
1643
1644 ei = (E->p[nblimbs] >> bufsize) & 1;
1645
1646 /*
1647 * skip leading 0s
1648 */
1649 if( ei == 0 && state == 0 )
1650 continue;
1651
1652 if( ei == 0 && state == 1 )
1653 {
1654 /*
1655 * out of window, square X
1656 */
1657 mpi_montmul( X, X, N, mm, &T );
1658 continue;
1659 }
1660
1661 /*
1662 * add ei to current window
1663 */
1664 state = 2;
1665
1666 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001667 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001668
1669 if( nbits == wsize )
1670 {
1671 /*
1672 * X = X^wsize R^-1 mod N
1673 */
1674 for( i = 0; i < wsize; i++ )
1675 mpi_montmul( X, X, N, mm, &T );
1676
1677 /*
1678 * X = X * W[wbits] R^-1 mod N
1679 */
1680 mpi_montmul( X, &W[wbits], N, mm, &T );
1681
1682 state--;
1683 nbits = 0;
1684 wbits = 0;
1685 }
1686 }
1687
1688 /*
1689 * process the remaining bits
1690 */
1691 for( i = 0; i < nbits; i++ )
1692 {
1693 mpi_montmul( X, X, N, mm, &T );
1694
1695 wbits <<= 1;
1696
Paul Bakker66d5d072014-06-17 16:39:18 +02001697 if( ( wbits & ( one << wsize ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001698 mpi_montmul( X, &W[1], N, mm, &T );
1699 }
1700
1701 /*
1702 * X = A^E * R * R^-1 mod N = A^E mod N
1703 */
1704 mpi_montred( X, N, mm, &T );
1705
Paul Bakkerf6198c12012-05-16 08:02:29 +00001706 if( neg )
1707 {
1708 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001709 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001710 }
1711
Paul Bakker5121ce52009-01-03 21:22:43 +00001712cleanup:
1713
Paul Bakker66d5d072014-06-17 16:39:18 +02001714 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001715 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001716
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001717 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001718
Paul Bakker75a28602014-03-31 12:08:17 +02001719 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001720 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001721
1722 return( ret );
1723}
1724
Paul Bakker5121ce52009-01-03 21:22:43 +00001725/*
1726 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1727 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001728int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001729{
Paul Bakker23986e52011-04-24 08:57:21 +00001730 int ret;
1731 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001732 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001733
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001734 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001735
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001736 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1737 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001738
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001739 lz = mbedtls_mpi_lsb( &TA );
1740 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001741
Paul Bakker66d5d072014-06-17 16:39:18 +02001742 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001743 lz = lzt;
1744
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001745 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1746 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001747
Paul Bakker5121ce52009-01-03 21:22:43 +00001748 TA.s = TB.s = 1;
1749
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001750 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001751 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001752 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1753 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001754
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001756 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001757 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1758 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001759 }
1760 else
1761 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001762 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1763 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001764 }
1765 }
1766
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001767 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1768 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001769
1770cleanup:
1771
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001772 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001773
1774 return( ret );
1775}
1776
Paul Bakker33dc46b2014-04-30 16:11:39 +02001777/*
1778 * Fill X with size bytes of random.
1779 *
1780 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02001781 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02001782 * deterministic, eg for tests).
1783 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001784int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001785 int (*f_rng)(void *, unsigned char *, size_t),
1786 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00001787{
Paul Bakker23986e52011-04-24 08:57:21 +00001788 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001789 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakker33dc46b2014-04-30 16:11:39 +02001790
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001791 if( size > MBEDTLS_MPI_MAX_SIZE )
1792 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00001793
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001794 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1795 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00001796
1797cleanup:
1798 return( ret );
1799}
1800
Paul Bakker5121ce52009-01-03 21:22:43 +00001801/*
1802 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1803 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001804int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001805{
1806 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001807 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001808
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001809 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 )
1810 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001811
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001812 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1813 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1814 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001815
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001817
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001818 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001819 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001820 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001821 goto cleanup;
1822 }
1823
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1825 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1826 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1827 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001828
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001829 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1830 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1831 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1832 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001833
1834 do
1835 {
1836 while( ( TU.p[0] & 1 ) == 0 )
1837 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001838 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001839
1840 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1841 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001842 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1843 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001844 }
1845
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001846 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1847 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001848 }
1849
1850 while( ( TV.p[0] & 1 ) == 0 )
1851 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001852 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001853
1854 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1855 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001856 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1857 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001858 }
1859
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001860 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1861 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001862 }
1863
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001864 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001865 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001866 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1867 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1868 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001869 }
1870 else
1871 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001872 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1873 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1874 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001875 }
1876 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001877 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001878
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1880 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001881
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1883 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001884
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001885 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001886
1887cleanup:
1888
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001889 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1890 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1891 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001892
1893 return( ret );
1894}
1895
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001896#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001897
Paul Bakker5121ce52009-01-03 21:22:43 +00001898static const int small_prime[] =
1899{
1900 3, 5, 7, 11, 13, 17, 19, 23,
1901 29, 31, 37, 41, 43, 47, 53, 59,
1902 61, 67, 71, 73, 79, 83, 89, 97,
1903 101, 103, 107, 109, 113, 127, 131, 137,
1904 139, 149, 151, 157, 163, 167, 173, 179,
1905 181, 191, 193, 197, 199, 211, 223, 227,
1906 229, 233, 239, 241, 251, 257, 263, 269,
1907 271, 277, 281, 283, 293, 307, 311, 313,
1908 317, 331, 337, 347, 349, 353, 359, 367,
1909 373, 379, 383, 389, 397, 401, 409, 419,
1910 421, 431, 433, 439, 443, 449, 457, 461,
1911 463, 467, 479, 487, 491, 499, 503, 509,
1912 521, 523, 541, 547, 557, 563, 569, 571,
1913 577, 587, 593, 599, 601, 607, 613, 617,
1914 619, 631, 641, 643, 647, 653, 659, 661,
1915 673, 677, 683, 691, 701, 709, 719, 727,
1916 733, 739, 743, 751, 757, 761, 769, 773,
1917 787, 797, 809, 811, 821, 823, 827, 829,
1918 839, 853, 857, 859, 863, 877, 881, 883,
1919 887, 907, 911, 919, 929, 937, 941, 947,
1920 953, 967, 971, 977, 983, 991, 997, -103
1921};
1922
1923/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001924 * Small divisors test (X must be positive)
1925 *
1926 * Return values:
1927 * 0: no small factor (possible prime, more tests needed)
1928 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001930 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00001931 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001932static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00001933{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001934 int ret = 0;
1935 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001936 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00001937
Paul Bakker5121ce52009-01-03 21:22:43 +00001938 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001939 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001940
1941 for( i = 0; small_prime[i] > 0; i++ )
1942 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001943 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001944 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001946 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001947
1948 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001949 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001950 }
1951
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001952cleanup:
1953 return( ret );
1954}
1955
1956/*
1957 * Miller-Rabin pseudo-primality test (HAC 4.24)
1958 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959static int mpi_miller_rabin( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001960 int (*f_rng)(void *, unsigned char *, size_t),
1961 void *p_rng )
1962{
Pascal Junodb99183d2015-03-11 16:49:45 +01001963 int ret, count;
1964 size_t i, j, k, n, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001965 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001966
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001967 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
1968 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01001969
Paul Bakker5121ce52009-01-03 21:22:43 +00001970 /*
1971 * W = |X| - 1
1972 * R = W >> lsb( W )
1973 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001974 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
1975 s = mbedtls_mpi_lsb( &W );
1976 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
1977 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001978
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001979 i = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +00001980 /*
1981 * HAC, table 4.4
1982 */
1983 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1984 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1985 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1986
1987 for( i = 0; i < n; i++ )
1988 {
1989 /*
1990 * pick a random A, 1 < A < |X| - 1
1991 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001992 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001993
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001994 if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
Paul Bakkerb94081b2011-01-05 15:53:06 +00001995 {
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001996 j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001997 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
Paul Bakkerb94081b2011-01-05 15:53:06 +00001998 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001999 A.p[0] |= 3;
2000
Pascal Junodb99183d2015-03-11 16:49:45 +01002001 count = 0;
2002 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002003 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002004
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002005 j = mbedtls_mpi_bitlen( &A );
2006 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002007 if (j > k) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002008 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002009 }
2010
2011 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002012 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002013 }
2014
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002015 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2016 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002017
2018 /*
2019 * A = A^R mod |X|
2020 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002021 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2024 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002025 continue;
2026
2027 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002028 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002029 {
2030 /*
2031 * A = A * A mod |X|
2032 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002033 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2034 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002035
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002036 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002037 break;
2038
2039 j++;
2040 }
2041
2042 /*
2043 * not prime if A != |X| - 1 or A == 1
2044 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002045 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2046 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002047 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002048 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002049 break;
2050 }
2051 }
2052
2053cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002054 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2055 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002056
2057 return( ret );
2058}
2059
2060/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002061 * Pseudo-primality test: small factors, then Miller-Rabin
2062 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002063int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002064 int (*f_rng)(void *, unsigned char *, size_t),
2065 void *p_rng )
2066{
2067 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002068 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002069
2070 XX.s = 1;
2071 XX.n = X->n;
2072 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002073
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002074 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2075 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2076 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002077
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002078 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002079 return( 0 );
2080
2081 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2082 {
2083 if( ret == 1 )
2084 return( 0 );
2085
2086 return( ret );
2087 }
2088
2089 return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2090}
2091
2092/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002093 * Prime number generation
2094 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002095int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002096 int (*f_rng)(void *, unsigned char *, size_t),
2097 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002098{
Paul Bakker23986e52011-04-24 08:57:21 +00002099 int ret;
2100 size_t k, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002101 mbedtls_mpi_uint r;
2102 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002103
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002104 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2105 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002107 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002108
2109 n = BITS_TO_LIMBS( nbits );
2110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002111 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002112
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002113 k = mbedtls_mpi_bitlen( X );
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002114 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002115
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002116 mbedtls_mpi_set_bit( X, nbits-1, 1 );
Pascal Junodb99183d2015-03-11 16:49:45 +01002117
2118 X->p[0] |= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002119
2120 if( dh_flag == 0 )
2121 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002122 while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002123 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002124 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002125 goto cleanup;
2126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002127 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002128 }
2129 }
2130 else
2131 {
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002132 /*
2133 * An necessary condition for Y and X = 2Y + 1 to be prime
2134 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2135 * Make sure it is satisfied, while keeping X = 3 mod 4
2136 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002137
2138 X->p[0] |= 2;
2139
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002140 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002141 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002142 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002143 else if( r == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002144 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002145
2146 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002147 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2148 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002149
2150 while( 1 )
2151 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002152 /*
2153 * First, check small factors for X and Y
2154 * before doing Miller-Rabin on any of them
2155 */
2156 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2157 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
2158 ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
2159 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002160 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002161 break;
Paul Bakker5121ce52009-01-03 21:22:43 +00002162 }
2163
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002164 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002165 goto cleanup;
2166
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002167 /*
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002168 * Next candidates. We want to preserve Y = (X-1) / 2 and
Manuel Pégourié-Gonnard0160eac2013-11-22 17:54:59 +01002169 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2170 * so up Y by 6 and X by 12.
2171 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002172 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2173 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002174 }
2175 }
2176
2177cleanup:
2178
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002179 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002180
2181 return( ret );
2182}
2183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002185
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002186#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002187
Paul Bakker23986e52011-04-24 08:57:21 +00002188#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002189
2190static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2191{
2192 { 693, 609, 21 },
2193 { 1764, 868, 28 },
2194 { 768454923, 542167814, 1 }
2195};
2196
Paul Bakker5121ce52009-01-03 21:22:43 +00002197/*
2198 * Checkup routine
2199 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002200int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002201{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002202 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002203 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002204
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002205 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2206 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002207
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002208 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002209 "EFE021C2645FD1DC586E69184AF4A31E" \
2210 "D5F53E93B5F123FA41680867BA110131" \
2211 "944FE7952E2517337780CB0DB80E61AA" \
2212 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2213
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002214 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002215 "B2E7EFD37075B9F03FF989C7C5051C20" \
2216 "34D2A323810251127E7BF8625A4F49A5" \
2217 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2218 "5B5C25763222FEFCCFC38B832366C29E" ) );
2219
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002220 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002221 "0066A198186C18C10B2F5ED9B522752A" \
2222 "9830B69916E535C8F047518A889A43A5" \
2223 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2224
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002225 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002227 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002228 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2229 "9E857EA95A03512E2BAE7391688D264A" \
2230 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2231 "8001B72E848A38CAE1C65F78E56ABDEF" \
2232 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2233 "ECF677152EF804370C1A305CAF3B5BF1" \
2234 "30879B56C61DE584A0F53A2447A51E" ) );
2235
2236 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002237 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002239 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002240 {
2241 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002242 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002243
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002244 ret = 1;
2245 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002246 }
2247
2248 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002249 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002250
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002251 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002252
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002253 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002254 "256567336059E52CAE22925474705F39A94" ) );
2255
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002256 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002257 "6613F26162223DF488E9CD48CC132C7A" \
2258 "0AC93C701B001B092E4E5B9F73BCD27B" \
2259 "9EE50D0657C77F374E903CDFA4C642" ) );
2260
2261 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002262 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2265 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002266 {
2267 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002268 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002269
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002270 ret = 1;
2271 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002272 }
2273
2274 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002275 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002276
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002277 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002278
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002279 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002280 "36E139AEA55215609D2816998ED020BB" \
2281 "BD96C37890F65171D948E9BC7CBAA4D9" \
2282 "325D24D6A3C12710F10A09FA08AB87" ) );
2283
2284 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002285 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002287 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002288 {
2289 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002290 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002291
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002292 ret = 1;
2293 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002294 }
2295
2296 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002297 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002300
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002301 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002302 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2303 "C3DBA76456363A10869622EAC2DD84EC" \
2304 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2305
2306 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002308
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002309 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002310 {
2311 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002312 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002313
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002314 ret = 1;
2315 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002316 }
2317
2318 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002319 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002320
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002321 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002322 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002323
Paul Bakker66d5d072014-06-17 16:39:18 +02002324 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002325 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002326 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2327 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002329 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002330
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002331 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002332 {
2333 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002334 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002335
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002336 ret = 1;
2337 goto cleanup;
2338 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002339 }
2340
2341 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002343
Paul Bakker5121ce52009-01-03 21:22:43 +00002344cleanup:
2345
2346 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002349 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2350 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002351
2352 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002354
2355 return( ret );
2356}
2357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002358#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002359
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002360#endif /* MBEDTLS_BIGNUM_C */