1c2c66affSColin Finck /*
2c2c66affSColin Finck * Multi-precision integer library
3c2c66affSColin Finck *
4218e2596SThomas Faber * Copyright The Mbed TLS Contributors
5e57126f5SThomas Faber * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6e57126f5SThomas Faber *
7e57126f5SThomas Faber * This file is provided under the Apache License 2.0, or the
8e57126f5SThomas Faber * GNU General Public License v2.0 or later.
9e57126f5SThomas Faber *
10e57126f5SThomas Faber * **********
11e57126f5SThomas Faber * Apache License 2.0:
12e57126f5SThomas Faber *
13e57126f5SThomas Faber * Licensed under the Apache License, Version 2.0 (the "License"); you may
14e57126f5SThomas Faber * not use this file except in compliance with the License.
15e57126f5SThomas Faber * You may obtain a copy of the License at
16e57126f5SThomas Faber *
17e57126f5SThomas Faber * http://www.apache.org/licenses/LICENSE-2.0
18e57126f5SThomas Faber *
19e57126f5SThomas Faber * Unless required by applicable law or agreed to in writing, software
20e57126f5SThomas Faber * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21e57126f5SThomas Faber * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22e57126f5SThomas Faber * See the License for the specific language governing permissions and
23e57126f5SThomas Faber * limitations under the License.
24e57126f5SThomas Faber *
25e57126f5SThomas Faber * **********
26e57126f5SThomas Faber *
27e57126f5SThomas Faber * **********
28e57126f5SThomas Faber * GNU General Public License v2.0 or later:
29c2c66affSColin Finck *
30c2c66affSColin Finck * This program is free software; you can redistribute it and/or modify
31c2c66affSColin Finck * it under the terms of the GNU General Public License as published by
32c2c66affSColin Finck * the Free Software Foundation; either version 2 of the License, or
33c2c66affSColin Finck * (at your option) any later version.
34c2c66affSColin Finck *
35c2c66affSColin Finck * This program is distributed in the hope that it will be useful,
36c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
37c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38c2c66affSColin Finck * GNU General Public License for more details.
39c2c66affSColin Finck *
40c2c66affSColin Finck * You should have received a copy of the GNU General Public License along
41c2c66affSColin Finck * with this program; if not, write to the Free Software Foundation, Inc.,
42c2c66affSColin Finck * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43c2c66affSColin Finck *
44e57126f5SThomas Faber * **********
45c2c66affSColin Finck */
46c2c66affSColin Finck
47c2c66affSColin Finck /*
48c2c66affSColin Finck * The following sources were referenced in the design of this Multi-precision
49c2c66affSColin Finck * Integer library:
50c2c66affSColin Finck *
51c2c66affSColin Finck * [1] Handbook of Applied Cryptography - 1997
52c2c66affSColin Finck * Menezes, van Oorschot and Vanstone
53c2c66affSColin Finck *
54c2c66affSColin Finck * [2] Multi-Precision Math
55c2c66affSColin Finck * Tom St Denis
56c2c66affSColin Finck * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
57c2c66affSColin Finck *
58c2c66affSColin Finck * [3] GNU Multi-Precision Arithmetic Library
59c2c66affSColin Finck * https://gmplib.org/manual/index.html
60c2c66affSColin Finck *
61c2c66affSColin Finck */
62c2c66affSColin Finck
63c2c66affSColin Finck #if !defined(MBEDTLS_CONFIG_FILE)
64c2c66affSColin Finck #include "mbedtls/config.h"
65c2c66affSColin Finck #else
66c2c66affSColin Finck #include MBEDTLS_CONFIG_FILE
67c2c66affSColin Finck #endif
68c2c66affSColin Finck
69c2c66affSColin Finck #if defined(MBEDTLS_BIGNUM_C)
70c2c66affSColin Finck
71c2c66affSColin Finck #include "mbedtls/bignum.h"
72c2c66affSColin Finck #include "mbedtls/bn_mul.h"
73cbda039fSThomas Faber #include "mbedtls/platform_util.h"
74c2c66affSColin Finck
75c2c66affSColin Finck #include <string.h>
76c2c66affSColin Finck
77c2c66affSColin Finck #if defined(MBEDTLS_PLATFORM_C)
78c2c66affSColin Finck #include "mbedtls/platform.h"
79c2c66affSColin Finck #else
80c2c66affSColin Finck #include <stdio.h>
81c2c66affSColin Finck #include <stdlib.h>
82c2c66affSColin Finck #define mbedtls_printf printf
83c2c66affSColin Finck #define mbedtls_calloc calloc
84c2c66affSColin Finck #define mbedtls_free free
85c2c66affSColin Finck #endif
86c2c66affSColin Finck
87cbda039fSThomas Faber #define MPI_VALIDATE_RET( cond ) \
88cbda039fSThomas Faber MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
89cbda039fSThomas Faber #define MPI_VALIDATE( cond ) \
90cbda039fSThomas Faber MBEDTLS_INTERNAL_VALIDATE( cond )
91d9e6c9b5SThomas Faber
92c2c66affSColin Finck #define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
93c2c66affSColin Finck #define biL (ciL << 3) /* bits in limb */
94c2c66affSColin Finck #define biH (ciL << 2) /* half limb size */
95c2c66affSColin Finck
96c2c66affSColin Finck #define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
97c2c66affSColin Finck
98c2c66affSColin Finck /*
99c2c66affSColin Finck * Convert between bits/chars and number of limbs
100c2c66affSColin Finck * Divide first in order to avoid potential overflows
101c2c66affSColin Finck */
102c2c66affSColin Finck #define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
103c2c66affSColin Finck #define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
104c2c66affSColin Finck
105cbda039fSThomas Faber /* Implementation that should never be optimized out by the compiler */
mbedtls_mpi_zeroize(mbedtls_mpi_uint * v,size_t n)106cbda039fSThomas Faber static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
107cbda039fSThomas Faber {
108cbda039fSThomas Faber mbedtls_platform_zeroize( v, ciL * n );
109cbda039fSThomas Faber }
110cbda039fSThomas Faber
111c2c66affSColin Finck /*
112c2c66affSColin Finck * Initialize one MPI
113c2c66affSColin Finck */
mbedtls_mpi_init(mbedtls_mpi * X)114c2c66affSColin Finck void mbedtls_mpi_init( mbedtls_mpi *X )
115c2c66affSColin Finck {
116cbda039fSThomas Faber MPI_VALIDATE( X != NULL );
117c2c66affSColin Finck
118c2c66affSColin Finck X->s = 1;
119c2c66affSColin Finck X->n = 0;
120c2c66affSColin Finck X->p = NULL;
121c2c66affSColin Finck }
122c2c66affSColin Finck
123c2c66affSColin Finck /*
124c2c66affSColin Finck * Unallocate one MPI
125c2c66affSColin Finck */
mbedtls_mpi_free(mbedtls_mpi * X)126c2c66affSColin Finck void mbedtls_mpi_free( mbedtls_mpi *X )
127c2c66affSColin Finck {
128c2c66affSColin Finck if( X == NULL )
129c2c66affSColin Finck return;
130c2c66affSColin Finck
131c2c66affSColin Finck if( X->p != NULL )
132c2c66affSColin Finck {
133c2c66affSColin Finck mbedtls_mpi_zeroize( X->p, X->n );
134c2c66affSColin Finck mbedtls_free( X->p );
135c2c66affSColin Finck }
136c2c66affSColin Finck
137c2c66affSColin Finck X->s = 1;
138c2c66affSColin Finck X->n = 0;
139c2c66affSColin Finck X->p = NULL;
140c2c66affSColin Finck }
141c2c66affSColin Finck
142c2c66affSColin Finck /*
143c2c66affSColin Finck * Enlarge to the specified number of limbs
144c2c66affSColin Finck */
mbedtls_mpi_grow(mbedtls_mpi * X,size_t nblimbs)145c2c66affSColin Finck int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
146c2c66affSColin Finck {
147c2c66affSColin Finck mbedtls_mpi_uint *p;
148cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
149c2c66affSColin Finck
150c2c66affSColin Finck if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
151c2c66affSColin Finck return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
152c2c66affSColin Finck
153c2c66affSColin Finck if( X->n < nblimbs )
154c2c66affSColin Finck {
155c2c66affSColin Finck if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
156c2c66affSColin Finck return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
157c2c66affSColin Finck
158c2c66affSColin Finck if( X->p != NULL )
159c2c66affSColin Finck {
160c2c66affSColin Finck memcpy( p, X->p, X->n * ciL );
161c2c66affSColin Finck mbedtls_mpi_zeroize( X->p, X->n );
162c2c66affSColin Finck mbedtls_free( X->p );
163c2c66affSColin Finck }
164c2c66affSColin Finck
165c2c66affSColin Finck X->n = nblimbs;
166c2c66affSColin Finck X->p = p;
167c2c66affSColin Finck }
168c2c66affSColin Finck
169c2c66affSColin Finck return( 0 );
170c2c66affSColin Finck }
171c2c66affSColin Finck
172c2c66affSColin Finck /*
173c2c66affSColin Finck * Resize down as much as possible,
174c2c66affSColin Finck * while keeping at least the specified number of limbs
175c2c66affSColin Finck */
mbedtls_mpi_shrink(mbedtls_mpi * X,size_t nblimbs)176c2c66affSColin Finck int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
177c2c66affSColin Finck {
178c2c66affSColin Finck mbedtls_mpi_uint *p;
179c2c66affSColin Finck size_t i;
180cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
181cbda039fSThomas Faber
182cbda039fSThomas Faber if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
183cbda039fSThomas Faber return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
184c2c66affSColin Finck
1851b00a1f5SThomas Faber /* Actually resize up if there are currently fewer than nblimbs limbs. */
186c2c66affSColin Finck if( X->n <= nblimbs )
187c2c66affSColin Finck return( mbedtls_mpi_grow( X, nblimbs ) );
1881b00a1f5SThomas Faber /* After this point, then X->n > nblimbs and in particular X->n > 0. */
189c2c66affSColin Finck
190c2c66affSColin Finck for( i = X->n - 1; i > 0; i-- )
191c2c66affSColin Finck if( X->p[i] != 0 )
192c2c66affSColin Finck break;
193c2c66affSColin Finck i++;
194c2c66affSColin Finck
195c2c66affSColin Finck if( i < nblimbs )
196c2c66affSColin Finck i = nblimbs;
197c2c66affSColin Finck
198c2c66affSColin Finck if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
199c2c66affSColin Finck return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
200c2c66affSColin Finck
201c2c66affSColin Finck if( X->p != NULL )
202c2c66affSColin Finck {
203c2c66affSColin Finck memcpy( p, X->p, i * ciL );
204c2c66affSColin Finck mbedtls_mpi_zeroize( X->p, X->n );
205c2c66affSColin Finck mbedtls_free( X->p );
206c2c66affSColin Finck }
207c2c66affSColin Finck
208c2c66affSColin Finck X->n = i;
209c2c66affSColin Finck X->p = p;
210c2c66affSColin Finck
211c2c66affSColin Finck return( 0 );
212c2c66affSColin Finck }
213c2c66affSColin Finck
214c2c66affSColin Finck /*
215c2c66affSColin Finck * Copy the contents of Y into X
216c2c66affSColin Finck */
mbedtls_mpi_copy(mbedtls_mpi * X,const mbedtls_mpi * Y)217c2c66affSColin Finck int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
218c2c66affSColin Finck {
219cbda039fSThomas Faber int ret = 0;
220c2c66affSColin Finck size_t i;
221cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
222cbda039fSThomas Faber MPI_VALIDATE_RET( Y != NULL );
223c2c66affSColin Finck
224c2c66affSColin Finck if( X == Y )
225c2c66affSColin Finck return( 0 );
226c2c66affSColin Finck
2271b00a1f5SThomas Faber if( Y->n == 0 )
228c2c66affSColin Finck {
229c2c66affSColin Finck mbedtls_mpi_free( X );
230c2c66affSColin Finck return( 0 );
231c2c66affSColin Finck }
232c2c66affSColin Finck
233c2c66affSColin Finck for( i = Y->n - 1; i > 0; i-- )
234c2c66affSColin Finck if( Y->p[i] != 0 )
235c2c66affSColin Finck break;
236c2c66affSColin Finck i++;
237c2c66affSColin Finck
238c2c66affSColin Finck X->s = Y->s;
239c2c66affSColin Finck
240cbda039fSThomas Faber if( X->n < i )
241cbda039fSThomas Faber {
242c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
243cbda039fSThomas Faber }
244cbda039fSThomas Faber else
245cbda039fSThomas Faber {
246cbda039fSThomas Faber memset( X->p + i, 0, ( X->n - i ) * ciL );
247cbda039fSThomas Faber }
248c2c66affSColin Finck
249c2c66affSColin Finck memcpy( X->p, Y->p, i * ciL );
250c2c66affSColin Finck
251c2c66affSColin Finck cleanup:
252c2c66affSColin Finck
253c2c66affSColin Finck return( ret );
254c2c66affSColin Finck }
255c2c66affSColin Finck
256c2c66affSColin Finck /*
257c2c66affSColin Finck * Swap the contents of X and Y
258c2c66affSColin Finck */
mbedtls_mpi_swap(mbedtls_mpi * X,mbedtls_mpi * Y)259c2c66affSColin Finck void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
260c2c66affSColin Finck {
261c2c66affSColin Finck mbedtls_mpi T;
262cbda039fSThomas Faber MPI_VALIDATE( X != NULL );
263cbda039fSThomas Faber MPI_VALIDATE( Y != NULL );
264c2c66affSColin Finck
265c2c66affSColin Finck memcpy( &T, X, sizeof( mbedtls_mpi ) );
266c2c66affSColin Finck memcpy( X, Y, sizeof( mbedtls_mpi ) );
267c2c66affSColin Finck memcpy( Y, &T, sizeof( mbedtls_mpi ) );
268c2c66affSColin Finck }
269c2c66affSColin Finck
270*103a79ceSThomas Faber /**
271*103a79ceSThomas Faber * Select between two sign values in constant-time.
272*103a79ceSThomas Faber *
273*103a79ceSThomas Faber * This is functionally equivalent to second ? a : b but uses only bit
274*103a79ceSThomas Faber * operations in order to avoid branches.
275*103a79ceSThomas Faber *
276*103a79ceSThomas Faber * \param[in] a The first sign; must be either +1 or -1.
277*103a79ceSThomas Faber * \param[in] b The second sign; must be either +1 or -1.
278*103a79ceSThomas Faber * \param[in] second Must be either 1 (return b) or 0 (return a).
279*103a79ceSThomas Faber *
280*103a79ceSThomas Faber * \return The selected sign value.
281*103a79ceSThomas Faber */
mpi_safe_cond_select_sign(int a,int b,unsigned char second)282*103a79ceSThomas Faber static int mpi_safe_cond_select_sign( int a, int b, unsigned char second )
283*103a79ceSThomas Faber {
284*103a79ceSThomas Faber /* In order to avoid questions about what we can reasonnably assume about
285*103a79ceSThomas Faber * the representations of signed integers, move everything to unsigned
286*103a79ceSThomas Faber * by taking advantage of the fact that a and b are either +1 or -1. */
287*103a79ceSThomas Faber unsigned ua = a + 1;
288*103a79ceSThomas Faber unsigned ub = b + 1;
289*103a79ceSThomas Faber
290*103a79ceSThomas Faber /* second was 0 or 1, mask is 0 or 2 as are ua and ub */
291*103a79ceSThomas Faber const unsigned mask = second << 1;
292*103a79ceSThomas Faber
293*103a79ceSThomas Faber /* select ua or ub */
294*103a79ceSThomas Faber unsigned ur = ( ua & ~mask ) | ( ub & mask );
295*103a79ceSThomas Faber
296*103a79ceSThomas Faber /* ur is now 0 or 2, convert back to -1 or +1 */
297*103a79ceSThomas Faber return( (int) ur - 1 );
298*103a79ceSThomas Faber }
299*103a79ceSThomas Faber
300c2c66affSColin Finck /*
301292f67afSThomas Faber * Conditionally assign dest = src, without leaking information
302292f67afSThomas Faber * about whether the assignment was made or not.
303292f67afSThomas Faber * dest and src must be arrays of limbs of size n.
304292f67afSThomas Faber * assign must be 0 or 1.
305292f67afSThomas Faber */
mpi_safe_cond_assign(size_t n,mbedtls_mpi_uint * dest,const mbedtls_mpi_uint * src,unsigned char assign)306292f67afSThomas Faber static void mpi_safe_cond_assign( size_t n,
307292f67afSThomas Faber mbedtls_mpi_uint *dest,
308292f67afSThomas Faber const mbedtls_mpi_uint *src,
309292f67afSThomas Faber unsigned char assign )
310292f67afSThomas Faber {
311292f67afSThomas Faber size_t i;
312*103a79ceSThomas Faber
313*103a79ceSThomas Faber /* MSVC has a warning about unary minus on unsigned integer types,
314*103a79ceSThomas Faber * but this is well-defined and precisely what we want to do here. */
315*103a79ceSThomas Faber #if defined(_MSC_VER)
316*103a79ceSThomas Faber #pragma warning( push )
317*103a79ceSThomas Faber #pragma warning( disable : 4146 )
318*103a79ceSThomas Faber #endif
319*103a79ceSThomas Faber
320*103a79ceSThomas Faber /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
321*103a79ceSThomas Faber const mbedtls_mpi_uint mask = -assign;
322*103a79ceSThomas Faber
323*103a79ceSThomas Faber #if defined(_MSC_VER)
324*103a79ceSThomas Faber #pragma warning( pop )
325*103a79ceSThomas Faber #endif
326*103a79ceSThomas Faber
327292f67afSThomas Faber for( i = 0; i < n; i++ )
328*103a79ceSThomas Faber dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask );
329292f67afSThomas Faber }
330292f67afSThomas Faber
331292f67afSThomas Faber /*
332c2c66affSColin Finck * Conditionally assign X = Y, without leaking information
333c2c66affSColin Finck * about whether the assignment was made or not.
334c2c66affSColin Finck * (Leaking information about the respective sizes of X and Y is ok however.)
335c2c66affSColin Finck */
mbedtls_mpi_safe_cond_assign(mbedtls_mpi * X,const mbedtls_mpi * Y,unsigned char assign)336c2c66affSColin Finck int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
337c2c66affSColin Finck {
338c2c66affSColin Finck int ret = 0;
339c2c66affSColin Finck size_t i;
340*103a79ceSThomas Faber mbedtls_mpi_uint limb_mask;
341cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
342cbda039fSThomas Faber MPI_VALIDATE_RET( Y != NULL );
343c2c66affSColin Finck
344*103a79ceSThomas Faber /* MSVC has a warning about unary minus on unsigned integer types,
345*103a79ceSThomas Faber * but this is well-defined and precisely what we want to do here. */
346*103a79ceSThomas Faber #if defined(_MSC_VER)
347*103a79ceSThomas Faber #pragma warning( push )
348*103a79ceSThomas Faber #pragma warning( disable : 4146 )
349*103a79ceSThomas Faber #endif
350*103a79ceSThomas Faber
351c2c66affSColin Finck /* make sure assign is 0 or 1 in a time-constant manner */
352*103a79ceSThomas Faber assign = (assign | (unsigned char)-assign) >> (sizeof( assign ) * 8 - 1);
353*103a79ceSThomas Faber /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
354*103a79ceSThomas Faber limb_mask = -assign;
355*103a79ceSThomas Faber
356*103a79ceSThomas Faber #if defined(_MSC_VER)
357*103a79ceSThomas Faber #pragma warning( pop )
358*103a79ceSThomas Faber #endif
359c2c66affSColin Finck
360c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
361c2c66affSColin Finck
362*103a79ceSThomas Faber X->s = mpi_safe_cond_select_sign( X->s, Y->s, assign );
363c2c66affSColin Finck
364292f67afSThomas Faber mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
365c2c66affSColin Finck
366292f67afSThomas Faber for( i = Y->n; i < X->n; i++ )
367*103a79ceSThomas Faber X->p[i] &= ~limb_mask;
368c2c66affSColin Finck
369c2c66affSColin Finck cleanup:
370c2c66affSColin Finck return( ret );
371c2c66affSColin Finck }
372c2c66affSColin Finck
373c2c66affSColin Finck /*
374c2c66affSColin Finck * Conditionally swap X and Y, without leaking information
375c2c66affSColin Finck * about whether the swap was made or not.
376c2c66affSColin Finck * Here it is not ok to simply swap the pointers, which whould lead to
377c2c66affSColin Finck * different memory access patterns when X and Y are used afterwards.
378c2c66affSColin Finck */
mbedtls_mpi_safe_cond_swap(mbedtls_mpi * X,mbedtls_mpi * Y,unsigned char swap)379c2c66affSColin Finck int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
380c2c66affSColin Finck {
381c2c66affSColin Finck int ret, s;
382c2c66affSColin Finck size_t i;
383*103a79ceSThomas Faber mbedtls_mpi_uint limb_mask;
384c2c66affSColin Finck mbedtls_mpi_uint tmp;
385cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
386cbda039fSThomas Faber MPI_VALIDATE_RET( Y != NULL );
387c2c66affSColin Finck
388c2c66affSColin Finck if( X == Y )
389c2c66affSColin Finck return( 0 );
390c2c66affSColin Finck
391*103a79ceSThomas Faber /* MSVC has a warning about unary minus on unsigned integer types,
392*103a79ceSThomas Faber * but this is well-defined and precisely what we want to do here. */
393*103a79ceSThomas Faber #if defined(_MSC_VER)
394*103a79ceSThomas Faber #pragma warning( push )
395*103a79ceSThomas Faber #pragma warning( disable : 4146 )
396*103a79ceSThomas Faber #endif
397*103a79ceSThomas Faber
398c2c66affSColin Finck /* make sure swap is 0 or 1 in a time-constant manner */
399*103a79ceSThomas Faber swap = (swap | (unsigned char)-swap) >> (sizeof( swap ) * 8 - 1);
400*103a79ceSThomas Faber /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
401*103a79ceSThomas Faber limb_mask = -swap;
402*103a79ceSThomas Faber
403*103a79ceSThomas Faber #if defined(_MSC_VER)
404*103a79ceSThomas Faber #pragma warning( pop )
405*103a79ceSThomas Faber #endif
406c2c66affSColin Finck
407c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
408c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
409c2c66affSColin Finck
410c2c66affSColin Finck s = X->s;
411*103a79ceSThomas Faber X->s = mpi_safe_cond_select_sign( X->s, Y->s, swap );
412*103a79ceSThomas Faber Y->s = mpi_safe_cond_select_sign( Y->s, s, swap );
413c2c66affSColin Finck
414c2c66affSColin Finck
415c2c66affSColin Finck for( i = 0; i < X->n; i++ )
416c2c66affSColin Finck {
417c2c66affSColin Finck tmp = X->p[i];
418*103a79ceSThomas Faber X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask );
419*103a79ceSThomas Faber Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask );
420c2c66affSColin Finck }
421c2c66affSColin Finck
422c2c66affSColin Finck cleanup:
423c2c66affSColin Finck return( ret );
424c2c66affSColin Finck }
425c2c66affSColin Finck
426c2c66affSColin Finck /*
427c2c66affSColin Finck * Set value from integer
428c2c66affSColin Finck */
mbedtls_mpi_lset(mbedtls_mpi * X,mbedtls_mpi_sint z)429c2c66affSColin Finck int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
430c2c66affSColin Finck {
431c2c66affSColin Finck int ret;
432cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
433c2c66affSColin Finck
434c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
435c2c66affSColin Finck memset( X->p, 0, X->n * ciL );
436c2c66affSColin Finck
437c2c66affSColin Finck X->p[0] = ( z < 0 ) ? -z : z;
438c2c66affSColin Finck X->s = ( z < 0 ) ? -1 : 1;
439c2c66affSColin Finck
440c2c66affSColin Finck cleanup:
441c2c66affSColin Finck
442c2c66affSColin Finck return( ret );
443c2c66affSColin Finck }
444c2c66affSColin Finck
445c2c66affSColin Finck /*
446c2c66affSColin Finck * Get a specific bit
447c2c66affSColin Finck */
mbedtls_mpi_get_bit(const mbedtls_mpi * X,size_t pos)448c2c66affSColin Finck int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
449c2c66affSColin Finck {
450cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
451cbda039fSThomas Faber
452c2c66affSColin Finck if( X->n * biL <= pos )
453c2c66affSColin Finck return( 0 );
454c2c66affSColin Finck
455c2c66affSColin Finck return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
456c2c66affSColin Finck }
457c2c66affSColin Finck
4580ba5bc40SThomas Faber /* Get a specific byte, without range checks. */
4590ba5bc40SThomas Faber #define GET_BYTE( X, i ) \
4600ba5bc40SThomas Faber ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
4610ba5bc40SThomas Faber
462c2c66affSColin Finck /*
463c2c66affSColin Finck * Set a bit to a specific value of 0 or 1
464c2c66affSColin Finck */
mbedtls_mpi_set_bit(mbedtls_mpi * X,size_t pos,unsigned char val)465c2c66affSColin Finck int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
466c2c66affSColin Finck {
467c2c66affSColin Finck int ret = 0;
468c2c66affSColin Finck size_t off = pos / biL;
469c2c66affSColin Finck size_t idx = pos % biL;
470cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
471c2c66affSColin Finck
472c2c66affSColin Finck if( val != 0 && val != 1 )
473c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
474c2c66affSColin Finck
475c2c66affSColin Finck if( X->n * biL <= pos )
476c2c66affSColin Finck {
477c2c66affSColin Finck if( val == 0 )
478c2c66affSColin Finck return( 0 );
479c2c66affSColin Finck
480c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
481c2c66affSColin Finck }
482c2c66affSColin Finck
483c2c66affSColin Finck X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
484c2c66affSColin Finck X->p[off] |= (mbedtls_mpi_uint) val << idx;
485c2c66affSColin Finck
486c2c66affSColin Finck cleanup:
487c2c66affSColin Finck
488c2c66affSColin Finck return( ret );
489c2c66affSColin Finck }
490c2c66affSColin Finck
491c2c66affSColin Finck /*
492c2c66affSColin Finck * Return the number of less significant zero-bits
493c2c66affSColin Finck */
mbedtls_mpi_lsb(const mbedtls_mpi * X)494c2c66affSColin Finck size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
495c2c66affSColin Finck {
496c2c66affSColin Finck size_t i, j, count = 0;
497cbda039fSThomas Faber MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
498c2c66affSColin Finck
499c2c66affSColin Finck for( i = 0; i < X->n; i++ )
500c2c66affSColin Finck for( j = 0; j < biL; j++, count++ )
501c2c66affSColin Finck if( ( ( X->p[i] >> j ) & 1 ) != 0 )
502c2c66affSColin Finck return( count );
503c2c66affSColin Finck
504c2c66affSColin Finck return( 0 );
505c2c66affSColin Finck }
506c2c66affSColin Finck
507c2c66affSColin Finck /*
508c2c66affSColin Finck * Count leading zero bits in a given integer
509c2c66affSColin Finck */
mbedtls_clz(const mbedtls_mpi_uint x)510c2c66affSColin Finck static size_t mbedtls_clz( const mbedtls_mpi_uint x )
511c2c66affSColin Finck {
512c2c66affSColin Finck size_t j;
513c2c66affSColin Finck mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
514c2c66affSColin Finck
515c2c66affSColin Finck for( j = 0; j < biL; j++ )
516c2c66affSColin Finck {
517c2c66affSColin Finck if( x & mask ) break;
518c2c66affSColin Finck
519c2c66affSColin Finck mask >>= 1;
520c2c66affSColin Finck }
521c2c66affSColin Finck
522c2c66affSColin Finck return j;
523c2c66affSColin Finck }
524c2c66affSColin Finck
525c2c66affSColin Finck /*
526c2c66affSColin Finck * Return the number of bits
527c2c66affSColin Finck */
mbedtls_mpi_bitlen(const mbedtls_mpi * X)528c2c66affSColin Finck size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
529c2c66affSColin Finck {
530c2c66affSColin Finck size_t i, j;
531c2c66affSColin Finck
532c2c66affSColin Finck if( X->n == 0 )
533c2c66affSColin Finck return( 0 );
534c2c66affSColin Finck
535c2c66affSColin Finck for( i = X->n - 1; i > 0; i-- )
536c2c66affSColin Finck if( X->p[i] != 0 )
537c2c66affSColin Finck break;
538c2c66affSColin Finck
539c2c66affSColin Finck j = biL - mbedtls_clz( X->p[i] );
540c2c66affSColin Finck
541c2c66affSColin Finck return( ( i * biL ) + j );
542c2c66affSColin Finck }
543c2c66affSColin Finck
544c2c66affSColin Finck /*
545c2c66affSColin Finck * Return the total size in bytes
546c2c66affSColin Finck */
mbedtls_mpi_size(const mbedtls_mpi * X)547c2c66affSColin Finck size_t mbedtls_mpi_size( const mbedtls_mpi *X )
548c2c66affSColin Finck {
549c2c66affSColin Finck return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
550c2c66affSColin Finck }
551c2c66affSColin Finck
552c2c66affSColin Finck /*
553c2c66affSColin Finck * Convert an ASCII character to digit value
554c2c66affSColin Finck */
mpi_get_digit(mbedtls_mpi_uint * d,int radix,char c)555c2c66affSColin Finck static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
556c2c66affSColin Finck {
557c2c66affSColin Finck *d = 255;
558c2c66affSColin Finck
559c2c66affSColin Finck if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
560c2c66affSColin Finck if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
561c2c66affSColin Finck if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
562c2c66affSColin Finck
563c2c66affSColin Finck if( *d >= (mbedtls_mpi_uint) radix )
564c2c66affSColin Finck return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
565c2c66affSColin Finck
566c2c66affSColin Finck return( 0 );
567c2c66affSColin Finck }
568c2c66affSColin Finck
569c2c66affSColin Finck /*
570c2c66affSColin Finck * Import from an ASCII string
571c2c66affSColin Finck */
mbedtls_mpi_read_string(mbedtls_mpi * X,int radix,const char * s)572c2c66affSColin Finck int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
573c2c66affSColin Finck {
574c2c66affSColin Finck int ret;
575c2c66affSColin Finck size_t i, j, slen, n;
576*103a79ceSThomas Faber int sign = 1;
577c2c66affSColin Finck mbedtls_mpi_uint d;
578c2c66affSColin Finck mbedtls_mpi T;
579cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
580cbda039fSThomas Faber MPI_VALIDATE_RET( s != NULL );
581c2c66affSColin Finck
582c2c66affSColin Finck if( radix < 2 || radix > 16 )
583c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
584c2c66affSColin Finck
585c2c66affSColin Finck mbedtls_mpi_init( &T );
586c2c66affSColin Finck
587*103a79ceSThomas Faber if( s[0] == '-' )
588*103a79ceSThomas Faber {
589*103a79ceSThomas Faber ++s;
590*103a79ceSThomas Faber sign = -1;
591*103a79ceSThomas Faber }
592*103a79ceSThomas Faber
593c2c66affSColin Finck slen = strlen( s );
594c2c66affSColin Finck
595c2c66affSColin Finck if( radix == 16 )
596c2c66affSColin Finck {
597c2c66affSColin Finck if( slen > MPI_SIZE_T_MAX >> 2 )
598c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
599c2c66affSColin Finck
600c2c66affSColin Finck n = BITS_TO_LIMBS( slen << 2 );
601c2c66affSColin Finck
602c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
603c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
604c2c66affSColin Finck
605c2c66affSColin Finck for( i = slen, j = 0; i > 0; i--, j++ )
606c2c66affSColin Finck {
607c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
608c2c66affSColin Finck X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
609c2c66affSColin Finck }
610c2c66affSColin Finck }
611c2c66affSColin Finck else
612c2c66affSColin Finck {
613c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
614c2c66affSColin Finck
615c2c66affSColin Finck for( i = 0; i < slen; i++ )
616c2c66affSColin Finck {
617c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
618c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
619c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
620c2c66affSColin Finck }
621c2c66affSColin Finck }
622*103a79ceSThomas Faber
623*103a79ceSThomas Faber if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
624*103a79ceSThomas Faber X->s = -1;
625c2c66affSColin Finck
626c2c66affSColin Finck cleanup:
627c2c66affSColin Finck
628c2c66affSColin Finck mbedtls_mpi_free( &T );
629c2c66affSColin Finck
630c2c66affSColin Finck return( ret );
631c2c66affSColin Finck }
632c2c66affSColin Finck
633c2c66affSColin Finck /*
634ca86ee9cSThomas Faber * Helper to write the digits high-order first.
635c2c66affSColin Finck */
mpi_write_hlp(mbedtls_mpi * X,int radix,char ** p,const size_t buflen)636ca86ee9cSThomas Faber static int mpi_write_hlp( mbedtls_mpi *X, int radix,
637ca86ee9cSThomas Faber char **p, const size_t buflen )
638c2c66affSColin Finck {
639c2c66affSColin Finck int ret;
640c2c66affSColin Finck mbedtls_mpi_uint r;
641ca86ee9cSThomas Faber size_t length = 0;
642ca86ee9cSThomas Faber char *p_end = *p + buflen;
643c2c66affSColin Finck
644ca86ee9cSThomas Faber do
645ca86ee9cSThomas Faber {
646ca86ee9cSThomas Faber if( length >= buflen )
647ca86ee9cSThomas Faber {
648ca86ee9cSThomas Faber return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
649ca86ee9cSThomas Faber }
650c2c66affSColin Finck
651c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
652c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
653ca86ee9cSThomas Faber /*
654ca86ee9cSThomas Faber * Write the residue in the current position, as an ASCII character.
655ca86ee9cSThomas Faber */
656ca86ee9cSThomas Faber if( r < 0xA )
657ca86ee9cSThomas Faber *(--p_end) = (char)( '0' + r );
658c2c66affSColin Finck else
659ca86ee9cSThomas Faber *(--p_end) = (char)( 'A' + ( r - 0xA ) );
660ca86ee9cSThomas Faber
661ca86ee9cSThomas Faber length++;
662ca86ee9cSThomas Faber } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
663ca86ee9cSThomas Faber
664ca86ee9cSThomas Faber memmove( *p, p_end, length );
665ca86ee9cSThomas Faber *p += length;
666c2c66affSColin Finck
667c2c66affSColin Finck cleanup:
668c2c66affSColin Finck
669c2c66affSColin Finck return( ret );
670c2c66affSColin Finck }
671c2c66affSColin Finck
672c2c66affSColin Finck /*
673c2c66affSColin Finck * Export into an ASCII string
674c2c66affSColin Finck */
mbedtls_mpi_write_string(const mbedtls_mpi * X,int radix,char * buf,size_t buflen,size_t * olen)675c2c66affSColin Finck int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
676c2c66affSColin Finck char *buf, size_t buflen, size_t *olen )
677c2c66affSColin Finck {
678c2c66affSColin Finck int ret = 0;
679c2c66affSColin Finck size_t n;
680c2c66affSColin Finck char *p;
681c2c66affSColin Finck mbedtls_mpi T;
682cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
683cbda039fSThomas Faber MPI_VALIDATE_RET( olen != NULL );
684cbda039fSThomas Faber MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
685c2c66affSColin Finck
686c2c66affSColin Finck if( radix < 2 || radix > 16 )
687c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
688c2c66affSColin Finck
689430656f0SThomas Faber n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
690430656f0SThomas Faber if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
691430656f0SThomas Faber * `n`. If radix > 4, this might be a strict
692430656f0SThomas Faber * overapproximation of the number of
693430656f0SThomas Faber * radix-adic digits needed to present `n`. */
694430656f0SThomas Faber if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
695430656f0SThomas Faber * present `n`. */
696430656f0SThomas Faber
697430656f0SThomas Faber n += 1; /* Terminating null byte */
698430656f0SThomas Faber n += 1; /* Compensate for the divisions above, which round down `n`
699430656f0SThomas Faber * in case it's not even. */
700430656f0SThomas Faber n += 1; /* Potential '-'-sign. */
701430656f0SThomas Faber n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
702430656f0SThomas Faber * which always uses an even number of hex-digits. */
703c2c66affSColin Finck
704c2c66affSColin Finck if( buflen < n )
705c2c66affSColin Finck {
706c2c66affSColin Finck *olen = n;
707c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
708c2c66affSColin Finck }
709c2c66affSColin Finck
710c2c66affSColin Finck p = buf;
711c2c66affSColin Finck mbedtls_mpi_init( &T );
712c2c66affSColin Finck
713c2c66affSColin Finck if( X->s == -1 )
714430656f0SThomas Faber {
715c2c66affSColin Finck *p++ = '-';
716430656f0SThomas Faber buflen--;
717430656f0SThomas Faber }
718c2c66affSColin Finck
719c2c66affSColin Finck if( radix == 16 )
720c2c66affSColin Finck {
721c2c66affSColin Finck int c;
722c2c66affSColin Finck size_t i, j, k;
723c2c66affSColin Finck
724c2c66affSColin Finck for( i = X->n, k = 0; i > 0; i-- )
725c2c66affSColin Finck {
726c2c66affSColin Finck for( j = ciL; j > 0; j-- )
727c2c66affSColin Finck {
728c2c66affSColin Finck c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
729c2c66affSColin Finck
730c2c66affSColin Finck if( c == 0 && k == 0 && ( i + j ) != 2 )
731c2c66affSColin Finck continue;
732c2c66affSColin Finck
733c2c66affSColin Finck *(p++) = "0123456789ABCDEF" [c / 16];
734c2c66affSColin Finck *(p++) = "0123456789ABCDEF" [c % 16];
735c2c66affSColin Finck k = 1;
736c2c66affSColin Finck }
737c2c66affSColin Finck }
738c2c66affSColin Finck }
739c2c66affSColin Finck else
740c2c66affSColin Finck {
741c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
742c2c66affSColin Finck
743c2c66affSColin Finck if( T.s == -1 )
744c2c66affSColin Finck T.s = 1;
745c2c66affSColin Finck
746ca86ee9cSThomas Faber MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
747c2c66affSColin Finck }
748c2c66affSColin Finck
749c2c66affSColin Finck *p++ = '\0';
750c2c66affSColin Finck *olen = p - buf;
751c2c66affSColin Finck
752c2c66affSColin Finck cleanup:
753c2c66affSColin Finck
754c2c66affSColin Finck mbedtls_mpi_free( &T );
755c2c66affSColin Finck
756c2c66affSColin Finck return( ret );
757c2c66affSColin Finck }
758c2c66affSColin Finck
759c2c66affSColin Finck #if defined(MBEDTLS_FS_IO)
760c2c66affSColin Finck /*
761c2c66affSColin Finck * Read X from an opened file
762c2c66affSColin Finck */
mbedtls_mpi_read_file(mbedtls_mpi * X,int radix,FILE * fin)763c2c66affSColin Finck int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
764c2c66affSColin Finck {
765c2c66affSColin Finck mbedtls_mpi_uint d;
766c2c66affSColin Finck size_t slen;
767c2c66affSColin Finck char *p;
768c2c66affSColin Finck /*
769c2c66affSColin Finck * Buffer should have space for (short) label and decimal formatted MPI,
770c2c66affSColin Finck * newline characters and '\0'
771c2c66affSColin Finck */
772c2c66affSColin Finck char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
773c2c66affSColin Finck
774cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
775cbda039fSThomas Faber MPI_VALIDATE_RET( fin != NULL );
776cbda039fSThomas Faber
777cbda039fSThomas Faber if( radix < 2 || radix > 16 )
778cbda039fSThomas Faber return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
779cbda039fSThomas Faber
780c2c66affSColin Finck memset( s, 0, sizeof( s ) );
781c2c66affSColin Finck if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
782c2c66affSColin Finck return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
783c2c66affSColin Finck
784c2c66affSColin Finck slen = strlen( s );
785c2c66affSColin Finck if( slen == sizeof( s ) - 2 )
786c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
787c2c66affSColin Finck
788c2c66affSColin Finck if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
789c2c66affSColin Finck if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
790c2c66affSColin Finck
791c2c66affSColin Finck p = s + slen;
792c2c66affSColin Finck while( p-- > s )
793c2c66affSColin Finck if( mpi_get_digit( &d, radix, *p ) != 0 )
794c2c66affSColin Finck break;
795c2c66affSColin Finck
796c2c66affSColin Finck return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
797c2c66affSColin Finck }
798c2c66affSColin Finck
799c2c66affSColin Finck /*
800c2c66affSColin Finck * Write X into an opened file (or stdout if fout == NULL)
801c2c66affSColin Finck */
mbedtls_mpi_write_file(const char * p,const mbedtls_mpi * X,int radix,FILE * fout)802c2c66affSColin Finck int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
803c2c66affSColin Finck {
804c2c66affSColin Finck int ret;
805c2c66affSColin Finck size_t n, slen, plen;
806c2c66affSColin Finck /*
807c2c66affSColin Finck * Buffer should have space for (short) label and decimal formatted MPI,
808c2c66affSColin Finck * newline characters and '\0'
809c2c66affSColin Finck */
810c2c66affSColin Finck char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
811cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
812cbda039fSThomas Faber
813cbda039fSThomas Faber if( radix < 2 || radix > 16 )
814cbda039fSThomas Faber return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
815c2c66affSColin Finck
816c2c66affSColin Finck memset( s, 0, sizeof( s ) );
817c2c66affSColin Finck
818c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
819c2c66affSColin Finck
820c2c66affSColin Finck if( p == NULL ) p = "";
821c2c66affSColin Finck
822c2c66affSColin Finck plen = strlen( p );
823c2c66affSColin Finck slen = strlen( s );
824c2c66affSColin Finck s[slen++] = '\r';
825c2c66affSColin Finck s[slen++] = '\n';
826c2c66affSColin Finck
827c2c66affSColin Finck if( fout != NULL )
828c2c66affSColin Finck {
829c2c66affSColin Finck if( fwrite( p, 1, plen, fout ) != plen ||
830c2c66affSColin Finck fwrite( s, 1, slen, fout ) != slen )
831c2c66affSColin Finck return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
832c2c66affSColin Finck }
833c2c66affSColin Finck else
834c2c66affSColin Finck mbedtls_printf( "%s%s", p, s );
835c2c66affSColin Finck
836c2c66affSColin Finck cleanup:
837c2c66affSColin Finck
838c2c66affSColin Finck return( ret );
839c2c66affSColin Finck }
840c2c66affSColin Finck #endif /* MBEDTLS_FS_IO */
841c2c66affSColin Finck
842cbda039fSThomas Faber
843cbda039fSThomas Faber /* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
844cbda039fSThomas Faber * into the storage form used by mbedtls_mpi. */
845cbda039fSThomas Faber
mpi_uint_bigendian_to_host_c(mbedtls_mpi_uint x)846cbda039fSThomas Faber static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
847cbda039fSThomas Faber {
848cbda039fSThomas Faber uint8_t i;
849cbda039fSThomas Faber unsigned char *x_ptr;
850cbda039fSThomas Faber mbedtls_mpi_uint tmp = 0;
851cbda039fSThomas Faber
852cbda039fSThomas Faber for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
853cbda039fSThomas Faber {
854cbda039fSThomas Faber tmp <<= CHAR_BIT;
855cbda039fSThomas Faber tmp |= (mbedtls_mpi_uint) *x_ptr;
856cbda039fSThomas Faber }
857cbda039fSThomas Faber
858cbda039fSThomas Faber return( tmp );
859cbda039fSThomas Faber }
860cbda039fSThomas Faber
mpi_uint_bigendian_to_host(mbedtls_mpi_uint x)861cbda039fSThomas Faber static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
862cbda039fSThomas Faber {
863cbda039fSThomas Faber #if defined(__BYTE_ORDER__)
864cbda039fSThomas Faber
865cbda039fSThomas Faber /* Nothing to do on bigendian systems. */
866cbda039fSThomas Faber #if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
867cbda039fSThomas Faber return( x );
868cbda039fSThomas Faber #endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
869cbda039fSThomas Faber
870cbda039fSThomas Faber #if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
871cbda039fSThomas Faber
872cbda039fSThomas Faber /* For GCC and Clang, have builtins for byte swapping. */
873cbda039fSThomas Faber #if defined(__GNUC__) && defined(__GNUC_PREREQ)
874cbda039fSThomas Faber #if __GNUC_PREREQ(4,3)
875cbda039fSThomas Faber #define have_bswap
876cbda039fSThomas Faber #endif
877cbda039fSThomas Faber #endif
878cbda039fSThomas Faber
879cbda039fSThomas Faber #if defined(__clang__) && defined(__has_builtin)
880cbda039fSThomas Faber #if __has_builtin(__builtin_bswap32) && \
881cbda039fSThomas Faber __has_builtin(__builtin_bswap64)
882cbda039fSThomas Faber #define have_bswap
883cbda039fSThomas Faber #endif
884cbda039fSThomas Faber #endif
885cbda039fSThomas Faber
886cbda039fSThomas Faber #if defined(have_bswap)
887cbda039fSThomas Faber /* The compiler is hopefully able to statically evaluate this! */
888cbda039fSThomas Faber switch( sizeof(mbedtls_mpi_uint) )
889cbda039fSThomas Faber {
890cbda039fSThomas Faber case 4:
891cbda039fSThomas Faber return( __builtin_bswap32(x) );
892cbda039fSThomas Faber case 8:
893cbda039fSThomas Faber return( __builtin_bswap64(x) );
894cbda039fSThomas Faber }
895cbda039fSThomas Faber #endif
896cbda039fSThomas Faber #endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
897cbda039fSThomas Faber #endif /* __BYTE_ORDER__ */
898cbda039fSThomas Faber
899cbda039fSThomas Faber /* Fall back to C-based reordering if we don't know the byte order
900cbda039fSThomas Faber * or we couldn't use a compiler-specific builtin. */
901cbda039fSThomas Faber return( mpi_uint_bigendian_to_host_c( x ) );
902cbda039fSThomas Faber }
903cbda039fSThomas Faber
mpi_bigendian_to_host(mbedtls_mpi_uint * const p,size_t limbs)904cbda039fSThomas Faber static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
905cbda039fSThomas Faber {
906cbda039fSThomas Faber mbedtls_mpi_uint *cur_limb_left;
907cbda039fSThomas Faber mbedtls_mpi_uint *cur_limb_right;
908cbda039fSThomas Faber if( limbs == 0 )
909cbda039fSThomas Faber return;
910cbda039fSThomas Faber
911cbda039fSThomas Faber /*
912cbda039fSThomas Faber * Traverse limbs and
913cbda039fSThomas Faber * - adapt byte-order in each limb
914cbda039fSThomas Faber * - swap the limbs themselves.
915cbda039fSThomas Faber * For that, simultaneously traverse the limbs from left to right
916cbda039fSThomas Faber * and from right to left, as long as the left index is not bigger
917cbda039fSThomas Faber * than the right index (it's not a problem if limbs is odd and the
918cbda039fSThomas Faber * indices coincide in the last iteration).
919cbda039fSThomas Faber */
920cbda039fSThomas Faber for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
921cbda039fSThomas Faber cur_limb_left <= cur_limb_right;
922cbda039fSThomas Faber cur_limb_left++, cur_limb_right-- )
923cbda039fSThomas Faber {
924cbda039fSThomas Faber mbedtls_mpi_uint tmp;
925cbda039fSThomas Faber /* Note that if cur_limb_left == cur_limb_right,
926cbda039fSThomas Faber * this code effectively swaps the bytes only once. */
927cbda039fSThomas Faber tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
928cbda039fSThomas Faber *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
929cbda039fSThomas Faber *cur_limb_right = tmp;
930cbda039fSThomas Faber }
931cbda039fSThomas Faber }
932cbda039fSThomas Faber
933c2c66affSColin Finck /*
934c2c66affSColin Finck * Import X from unsigned binary data, big endian
935c2c66affSColin Finck */
mbedtls_mpi_read_binary(mbedtls_mpi * X,const unsigned char * buf,size_t buflen)936c2c66affSColin Finck int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
937c2c66affSColin Finck {
938c2c66affSColin Finck int ret;
939d9e6c9b5SThomas Faber size_t const limbs = CHARS_TO_LIMBS( buflen );
940cbda039fSThomas Faber size_t const overhead = ( limbs * ciL ) - buflen;
941cbda039fSThomas Faber unsigned char *Xp;
942cbda039fSThomas Faber
943cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
944cbda039fSThomas Faber MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
945c2c66affSColin Finck
946d9e6c9b5SThomas Faber /* Ensure that target MPI has exactly the necessary number of limbs */
947d9e6c9b5SThomas Faber if( X->n != limbs )
948d9e6c9b5SThomas Faber {
949d9e6c9b5SThomas Faber mbedtls_mpi_free( X );
950d9e6c9b5SThomas Faber mbedtls_mpi_init( X );
951d9e6c9b5SThomas Faber MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
952d9e6c9b5SThomas Faber }
953c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
954c2c66affSColin Finck
955cbda039fSThomas Faber /* Avoid calling `memcpy` with NULL source argument,
956cbda039fSThomas Faber * even if buflen is 0. */
957cbda039fSThomas Faber if( buf != NULL )
958cbda039fSThomas Faber {
959cbda039fSThomas Faber Xp = (unsigned char*) X->p;
960cbda039fSThomas Faber memcpy( Xp + overhead, buf, buflen );
961cbda039fSThomas Faber
962cbda039fSThomas Faber mpi_bigendian_to_host( X->p, limbs );
963cbda039fSThomas Faber }
964c2c66affSColin Finck
965c2c66affSColin Finck cleanup:
966c2c66affSColin Finck
967c2c66affSColin Finck return( ret );
968c2c66affSColin Finck }
969c2c66affSColin Finck
970c2c66affSColin Finck /*
971c2c66affSColin Finck * Export X into unsigned binary data, big endian
972c2c66affSColin Finck */
mbedtls_mpi_write_binary(const mbedtls_mpi * X,unsigned char * buf,size_t buflen)9730ba5bc40SThomas Faber int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
9740ba5bc40SThomas Faber unsigned char *buf, size_t buflen )
975c2c66affSColin Finck {
976cbda039fSThomas Faber size_t stored_bytes;
9770ba5bc40SThomas Faber size_t bytes_to_copy;
9780ba5bc40SThomas Faber unsigned char *p;
9790ba5bc40SThomas Faber size_t i;
980c2c66affSColin Finck
981cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
982cbda039fSThomas Faber MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
983cbda039fSThomas Faber
984cbda039fSThomas Faber stored_bytes = X->n * ciL;
985cbda039fSThomas Faber
9860ba5bc40SThomas Faber if( stored_bytes < buflen )
9870ba5bc40SThomas Faber {
9880ba5bc40SThomas Faber /* There is enough space in the output buffer. Write initial
9890ba5bc40SThomas Faber * null bytes and record the position at which to start
9900ba5bc40SThomas Faber * writing the significant bytes. In this case, the execution
9910ba5bc40SThomas Faber * trace of this function does not depend on the value of the
9920ba5bc40SThomas Faber * number. */
9930ba5bc40SThomas Faber bytes_to_copy = stored_bytes;
9940ba5bc40SThomas Faber p = buf + buflen - stored_bytes;
9950ba5bc40SThomas Faber memset( buf, 0, buflen - stored_bytes );
9960ba5bc40SThomas Faber }
9970ba5bc40SThomas Faber else
9980ba5bc40SThomas Faber {
9990ba5bc40SThomas Faber /* The output buffer is smaller than the allocated size of X.
10000ba5bc40SThomas Faber * However X may fit if its leading bytes are zero. */
10010ba5bc40SThomas Faber bytes_to_copy = buflen;
10020ba5bc40SThomas Faber p = buf;
10030ba5bc40SThomas Faber for( i = bytes_to_copy; i < stored_bytes; i++ )
10040ba5bc40SThomas Faber {
10050ba5bc40SThomas Faber if( GET_BYTE( X, i ) != 0 )
1006c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
10070ba5bc40SThomas Faber }
10080ba5bc40SThomas Faber }
1009c2c66affSColin Finck
10100ba5bc40SThomas Faber for( i = 0; i < bytes_to_copy; i++ )
10110ba5bc40SThomas Faber p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
1012c2c66affSColin Finck
1013c2c66affSColin Finck return( 0 );
1014c2c66affSColin Finck }
1015c2c66affSColin Finck
1016c2c66affSColin Finck /*
1017c2c66affSColin Finck * Left-shift: X <<= count
1018c2c66affSColin Finck */
mbedtls_mpi_shift_l(mbedtls_mpi * X,size_t count)1019c2c66affSColin Finck int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
1020c2c66affSColin Finck {
1021c2c66affSColin Finck int ret;
1022c2c66affSColin Finck size_t i, v0, t1;
1023c2c66affSColin Finck mbedtls_mpi_uint r0 = 0, r1;
1024cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
1025c2c66affSColin Finck
1026c2c66affSColin Finck v0 = count / (biL );
1027c2c66affSColin Finck t1 = count & (biL - 1);
1028c2c66affSColin Finck
1029c2c66affSColin Finck i = mbedtls_mpi_bitlen( X ) + count;
1030c2c66affSColin Finck
1031c2c66affSColin Finck if( X->n * biL < i )
1032c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
1033c2c66affSColin Finck
1034c2c66affSColin Finck ret = 0;
1035c2c66affSColin Finck
1036c2c66affSColin Finck /*
1037c2c66affSColin Finck * shift by count / limb_size
1038c2c66affSColin Finck */
1039c2c66affSColin Finck if( v0 > 0 )
1040c2c66affSColin Finck {
1041c2c66affSColin Finck for( i = X->n; i > v0; i-- )
1042c2c66affSColin Finck X->p[i - 1] = X->p[i - v0 - 1];
1043c2c66affSColin Finck
1044c2c66affSColin Finck for( ; i > 0; i-- )
1045c2c66affSColin Finck X->p[i - 1] = 0;
1046c2c66affSColin Finck }
1047c2c66affSColin Finck
1048c2c66affSColin Finck /*
1049c2c66affSColin Finck * shift by count % limb_size
1050c2c66affSColin Finck */
1051c2c66affSColin Finck if( t1 > 0 )
1052c2c66affSColin Finck {
1053c2c66affSColin Finck for( i = v0; i < X->n; i++ )
1054c2c66affSColin Finck {
1055c2c66affSColin Finck r1 = X->p[i] >> (biL - t1);
1056c2c66affSColin Finck X->p[i] <<= t1;
1057c2c66affSColin Finck X->p[i] |= r0;
1058c2c66affSColin Finck r0 = r1;
1059c2c66affSColin Finck }
1060c2c66affSColin Finck }
1061c2c66affSColin Finck
1062c2c66affSColin Finck cleanup:
1063c2c66affSColin Finck
1064c2c66affSColin Finck return( ret );
1065c2c66affSColin Finck }
1066c2c66affSColin Finck
1067c2c66affSColin Finck /*
1068c2c66affSColin Finck * Right-shift: X >>= count
1069c2c66affSColin Finck */
mbedtls_mpi_shift_r(mbedtls_mpi * X,size_t count)1070c2c66affSColin Finck int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
1071c2c66affSColin Finck {
1072c2c66affSColin Finck size_t i, v0, v1;
1073c2c66affSColin Finck mbedtls_mpi_uint r0 = 0, r1;
1074cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
1075c2c66affSColin Finck
1076c2c66affSColin Finck v0 = count / biL;
1077c2c66affSColin Finck v1 = count & (biL - 1);
1078c2c66affSColin Finck
1079c2c66affSColin Finck if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
1080c2c66affSColin Finck return mbedtls_mpi_lset( X, 0 );
1081c2c66affSColin Finck
1082c2c66affSColin Finck /*
1083c2c66affSColin Finck * shift by count / limb_size
1084c2c66affSColin Finck */
1085c2c66affSColin Finck if( v0 > 0 )
1086c2c66affSColin Finck {
1087c2c66affSColin Finck for( i = 0; i < X->n - v0; i++ )
1088c2c66affSColin Finck X->p[i] = X->p[i + v0];
1089c2c66affSColin Finck
1090c2c66affSColin Finck for( ; i < X->n; i++ )
1091c2c66affSColin Finck X->p[i] = 0;
1092c2c66affSColin Finck }
1093c2c66affSColin Finck
1094c2c66affSColin Finck /*
1095c2c66affSColin Finck * shift by count % limb_size
1096c2c66affSColin Finck */
1097c2c66affSColin Finck if( v1 > 0 )
1098c2c66affSColin Finck {
1099c2c66affSColin Finck for( i = X->n; i > 0; i-- )
1100c2c66affSColin Finck {
1101c2c66affSColin Finck r1 = X->p[i - 1] << (biL - v1);
1102c2c66affSColin Finck X->p[i - 1] >>= v1;
1103c2c66affSColin Finck X->p[i - 1] |= r0;
1104c2c66affSColin Finck r0 = r1;
1105c2c66affSColin Finck }
1106c2c66affSColin Finck }
1107c2c66affSColin Finck
1108c2c66affSColin Finck return( 0 );
1109c2c66affSColin Finck }
1110c2c66affSColin Finck
1111c2c66affSColin Finck /*
1112c2c66affSColin Finck * Compare unsigned values
1113c2c66affSColin Finck */
mbedtls_mpi_cmp_abs(const mbedtls_mpi * X,const mbedtls_mpi * Y)1114c2c66affSColin Finck int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
1115c2c66affSColin Finck {
1116c2c66affSColin Finck size_t i, j;
1117cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
1118cbda039fSThomas Faber MPI_VALIDATE_RET( Y != NULL );
1119c2c66affSColin Finck
1120c2c66affSColin Finck for( i = X->n; i > 0; i-- )
1121c2c66affSColin Finck if( X->p[i - 1] != 0 )
1122c2c66affSColin Finck break;
1123c2c66affSColin Finck
1124c2c66affSColin Finck for( j = Y->n; j > 0; j-- )
1125c2c66affSColin Finck if( Y->p[j - 1] != 0 )
1126c2c66affSColin Finck break;
1127c2c66affSColin Finck
1128c2c66affSColin Finck if( i == 0 && j == 0 )
1129c2c66affSColin Finck return( 0 );
1130c2c66affSColin Finck
1131c2c66affSColin Finck if( i > j ) return( 1 );
1132c2c66affSColin Finck if( j > i ) return( -1 );
1133c2c66affSColin Finck
1134c2c66affSColin Finck for( ; i > 0; i-- )
1135c2c66affSColin Finck {
1136c2c66affSColin Finck if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1137c2c66affSColin Finck if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
1138c2c66affSColin Finck }
1139c2c66affSColin Finck
1140c2c66affSColin Finck return( 0 );
1141c2c66affSColin Finck }
1142c2c66affSColin Finck
1143c2c66affSColin Finck /*
1144c2c66affSColin Finck * Compare signed values
1145c2c66affSColin Finck */
mbedtls_mpi_cmp_mpi(const mbedtls_mpi * X,const mbedtls_mpi * Y)1146c2c66affSColin Finck int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
1147c2c66affSColin Finck {
1148c2c66affSColin Finck size_t i, j;
1149cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
1150cbda039fSThomas Faber MPI_VALIDATE_RET( Y != NULL );
1151c2c66affSColin Finck
1152c2c66affSColin Finck for( i = X->n; i > 0; i-- )
1153c2c66affSColin Finck if( X->p[i - 1] != 0 )
1154c2c66affSColin Finck break;
1155c2c66affSColin Finck
1156c2c66affSColin Finck for( j = Y->n; j > 0; j-- )
1157c2c66affSColin Finck if( Y->p[j - 1] != 0 )
1158c2c66affSColin Finck break;
1159c2c66affSColin Finck
1160c2c66affSColin Finck if( i == 0 && j == 0 )
1161c2c66affSColin Finck return( 0 );
1162c2c66affSColin Finck
1163c2c66affSColin Finck if( i > j ) return( X->s );
1164c2c66affSColin Finck if( j > i ) return( -Y->s );
1165c2c66affSColin Finck
1166c2c66affSColin Finck if( X->s > 0 && Y->s < 0 ) return( 1 );
1167c2c66affSColin Finck if( Y->s > 0 && X->s < 0 ) return( -1 );
1168c2c66affSColin Finck
1169c2c66affSColin Finck for( ; i > 0; i-- )
1170c2c66affSColin Finck {
1171c2c66affSColin Finck if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1172c2c66affSColin Finck if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
1173c2c66affSColin Finck }
1174c2c66affSColin Finck
1175c2c66affSColin Finck return( 0 );
1176c2c66affSColin Finck }
1177c2c66affSColin Finck
1178d152519aSThomas Faber /** Decide if an integer is less than the other, without branches.
1179d152519aSThomas Faber *
1180d152519aSThomas Faber * \param x First integer.
1181d152519aSThomas Faber * \param y Second integer.
1182d152519aSThomas Faber *
1183d152519aSThomas Faber * \return 1 if \p x is less than \p y, 0 otherwise
1184d152519aSThomas Faber */
ct_lt_mpi_uint(const mbedtls_mpi_uint x,const mbedtls_mpi_uint y)1185d152519aSThomas Faber static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1186d152519aSThomas Faber const mbedtls_mpi_uint y )
1187d152519aSThomas Faber {
1188d152519aSThomas Faber mbedtls_mpi_uint ret;
1189d152519aSThomas Faber mbedtls_mpi_uint cond;
1190d152519aSThomas Faber
1191d152519aSThomas Faber /*
1192d152519aSThomas Faber * Check if the most significant bits (MSB) of the operands are different.
1193d152519aSThomas Faber */
1194d152519aSThomas Faber cond = ( x ^ y );
1195d152519aSThomas Faber /*
1196d152519aSThomas Faber * If the MSB are the same then the difference x-y will be negative (and
1197d152519aSThomas Faber * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1198d152519aSThomas Faber */
1199d152519aSThomas Faber ret = ( x - y ) & ~cond;
1200d152519aSThomas Faber /*
1201d152519aSThomas Faber * If the MSB are different, then the operand with the MSB of 1 is the
1202d152519aSThomas Faber * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1203d152519aSThomas Faber * the MSB of y is 0.)
1204d152519aSThomas Faber */
1205d152519aSThomas Faber ret |= y & cond;
1206d152519aSThomas Faber
1207d152519aSThomas Faber
1208d152519aSThomas Faber ret = ret >> ( biL - 1 );
1209d152519aSThomas Faber
1210d152519aSThomas Faber return (unsigned) ret;
1211d152519aSThomas Faber }
1212d152519aSThomas Faber
1213d152519aSThomas Faber /*
1214d152519aSThomas Faber * Compare signed values in constant time
1215d152519aSThomas Faber */
mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi * X,const mbedtls_mpi * Y,unsigned * ret)1216d152519aSThomas Faber int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1217d152519aSThomas Faber unsigned *ret )
1218d152519aSThomas Faber {
1219d152519aSThomas Faber size_t i;
1220d152519aSThomas Faber /* The value of any of these variables is either 0 or 1 at all times. */
1221d152519aSThomas Faber unsigned cond, done, X_is_negative, Y_is_negative;
1222d152519aSThomas Faber
1223cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
1224cbda039fSThomas Faber MPI_VALIDATE_RET( Y != NULL );
1225cbda039fSThomas Faber MPI_VALIDATE_RET( ret != NULL );
1226cbda039fSThomas Faber
1227d152519aSThomas Faber if( X->n != Y->n )
1228d152519aSThomas Faber return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1229d152519aSThomas Faber
1230d152519aSThomas Faber /*
1231d152519aSThomas Faber * Set sign_N to 1 if N >= 0, 0 if N < 0.
1232d152519aSThomas Faber * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
1233d152519aSThomas Faber */
1234d152519aSThomas Faber X_is_negative = ( X->s & 2 ) >> 1;
1235d152519aSThomas Faber Y_is_negative = ( Y->s & 2 ) >> 1;
1236d152519aSThomas Faber
1237d152519aSThomas Faber /*
1238d152519aSThomas Faber * If the signs are different, then the positive operand is the bigger.
1239d152519aSThomas Faber * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1240d152519aSThomas Faber * is false if X is positive (X_is_negative == 0).
1241d152519aSThomas Faber */
1242d152519aSThomas Faber cond = ( X_is_negative ^ Y_is_negative );
1243d152519aSThomas Faber *ret = cond & X_is_negative;
1244d152519aSThomas Faber
1245d152519aSThomas Faber /*
1246d152519aSThomas Faber * This is a constant-time function. We might have the result, but we still
1247d152519aSThomas Faber * need to go through the loop. Record if we have the result already.
1248d152519aSThomas Faber */
1249d152519aSThomas Faber done = cond;
1250d152519aSThomas Faber
1251d152519aSThomas Faber for( i = X->n; i > 0; i-- )
1252d152519aSThomas Faber {
1253d152519aSThomas Faber /*
1254d152519aSThomas Faber * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1255d152519aSThomas Faber * X and Y are negative.
1256d152519aSThomas Faber *
1257d152519aSThomas Faber * Again even if we can make a decision, we just mark the result and
1258d152519aSThomas Faber * the fact that we are done and continue looping.
1259d152519aSThomas Faber */
1260d152519aSThomas Faber cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1261d152519aSThomas Faber *ret |= cond & ( 1 - done ) & X_is_negative;
1262d152519aSThomas Faber done |= cond;
1263d152519aSThomas Faber
1264d152519aSThomas Faber /*
1265d152519aSThomas Faber * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1266d152519aSThomas Faber * X and Y are positive.
1267d152519aSThomas Faber *
1268d152519aSThomas Faber * Again even if we can make a decision, we just mark the result and
1269d152519aSThomas Faber * the fact that we are done and continue looping.
1270d152519aSThomas Faber */
1271d152519aSThomas Faber cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1272d152519aSThomas Faber *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
1273d152519aSThomas Faber done |= cond;
1274d152519aSThomas Faber }
1275d152519aSThomas Faber
1276d152519aSThomas Faber return( 0 );
1277d152519aSThomas Faber }
1278d152519aSThomas Faber
1279c2c66affSColin Finck /*
1280c2c66affSColin Finck * Compare signed values
1281c2c66affSColin Finck */
mbedtls_mpi_cmp_int(const mbedtls_mpi * X,mbedtls_mpi_sint z)1282c2c66affSColin Finck int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
1283c2c66affSColin Finck {
1284c2c66affSColin Finck mbedtls_mpi Y;
1285c2c66affSColin Finck mbedtls_mpi_uint p[1];
1286cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
1287c2c66affSColin Finck
1288c2c66affSColin Finck *p = ( z < 0 ) ? -z : z;
1289c2c66affSColin Finck Y.s = ( z < 0 ) ? -1 : 1;
1290c2c66affSColin Finck Y.n = 1;
1291c2c66affSColin Finck Y.p = p;
1292c2c66affSColin Finck
1293c2c66affSColin Finck return( mbedtls_mpi_cmp_mpi( X, &Y ) );
1294c2c66affSColin Finck }
1295c2c66affSColin Finck
1296c2c66affSColin Finck /*
1297c2c66affSColin Finck * Unsigned addition: X = |A| + |B| (HAC 14.7)
1298c2c66affSColin Finck */
mbedtls_mpi_add_abs(mbedtls_mpi * X,const mbedtls_mpi * A,const mbedtls_mpi * B)1299c2c66affSColin Finck int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1300c2c66affSColin Finck {
1301c2c66affSColin Finck int ret;
1302c2c66affSColin Finck size_t i, j;
1303c2c66affSColin Finck mbedtls_mpi_uint *o, *p, c, tmp;
1304cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
1305cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL );
1306cbda039fSThomas Faber MPI_VALIDATE_RET( B != NULL );
1307c2c66affSColin Finck
1308c2c66affSColin Finck if( X == B )
1309c2c66affSColin Finck {
1310c2c66affSColin Finck const mbedtls_mpi *T = A; A = X; B = T;
1311c2c66affSColin Finck }
1312c2c66affSColin Finck
1313c2c66affSColin Finck if( X != A )
1314c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
1315c2c66affSColin Finck
1316c2c66affSColin Finck /*
1317c2c66affSColin Finck * X should always be positive as a result of unsigned additions.
1318c2c66affSColin Finck */
1319c2c66affSColin Finck X->s = 1;
1320c2c66affSColin Finck
1321c2c66affSColin Finck for( j = B->n; j > 0; j-- )
1322c2c66affSColin Finck if( B->p[j - 1] != 0 )
1323c2c66affSColin Finck break;
1324c2c66affSColin Finck
1325c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1326c2c66affSColin Finck
1327c2c66affSColin Finck o = B->p; p = X->p; c = 0;
1328c2c66affSColin Finck
1329c2c66affSColin Finck /*
1330c2c66affSColin Finck * tmp is used because it might happen that p == o
1331c2c66affSColin Finck */
1332c2c66affSColin Finck for( i = 0; i < j; i++, o++, p++ )
1333c2c66affSColin Finck {
1334c2c66affSColin Finck tmp= *o;
1335c2c66affSColin Finck *p += c; c = ( *p < c );
1336c2c66affSColin Finck *p += tmp; c += ( *p < tmp );
1337c2c66affSColin Finck }
1338c2c66affSColin Finck
1339c2c66affSColin Finck while( c != 0 )
1340c2c66affSColin Finck {
1341c2c66affSColin Finck if( i >= X->n )
1342c2c66affSColin Finck {
1343c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
1344c2c66affSColin Finck p = X->p + i;
1345c2c66affSColin Finck }
1346c2c66affSColin Finck
1347c2c66affSColin Finck *p += c; c = ( *p < c ); i++; p++;
1348c2c66affSColin Finck }
1349c2c66affSColin Finck
1350c2c66affSColin Finck cleanup:
1351c2c66affSColin Finck
1352c2c66affSColin Finck return( ret );
1353c2c66affSColin Finck }
1354c2c66affSColin Finck
1355292f67afSThomas Faber /**
1356292f67afSThomas Faber * Helper for mbedtls_mpi subtraction.
1357292f67afSThomas Faber *
1358292f67afSThomas Faber * Calculate d - s where d and s have the same size.
1359292f67afSThomas Faber * This function operates modulo (2^ciL)^n and returns the carry
1360292f67afSThomas Faber * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise).
1361292f67afSThomas Faber *
1362292f67afSThomas Faber * \param n Number of limbs of \p d and \p s.
1363292f67afSThomas Faber * \param[in,out] d On input, the left operand.
1364292f67afSThomas Faber * On output, the result of the subtraction:
1365292f67afSThomas Faber * \param[in] s The right operand.
1366292f67afSThomas Faber *
1367292f67afSThomas Faber * \return 1 if `d < s`.
1368292f67afSThomas Faber * 0 if `d >= s`.
1369c2c66affSColin Finck */
mpi_sub_hlp(size_t n,mbedtls_mpi_uint * d,const mbedtls_mpi_uint * s)1370292f67afSThomas Faber static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1371292f67afSThomas Faber mbedtls_mpi_uint *d,
1372292f67afSThomas Faber const mbedtls_mpi_uint *s )
1373c2c66affSColin Finck {
1374c2c66affSColin Finck size_t i;
1375c2c66affSColin Finck mbedtls_mpi_uint c, z;
1376c2c66affSColin Finck
1377c2c66affSColin Finck for( i = c = 0; i < n; i++, s++, d++ )
1378c2c66affSColin Finck {
1379c2c66affSColin Finck z = ( *d < c ); *d -= c;
1380c2c66affSColin Finck c = ( *d < *s ) + z; *d -= *s;
1381c2c66affSColin Finck }
1382c2c66affSColin Finck
1383292f67afSThomas Faber return( c );
1384c2c66affSColin Finck }
1385c2c66affSColin Finck
1386c2c66affSColin Finck /*
1387292f67afSThomas Faber * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
1388c2c66affSColin Finck */
mbedtls_mpi_sub_abs(mbedtls_mpi * X,const mbedtls_mpi * A,const mbedtls_mpi * B)1389c2c66affSColin Finck int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1390c2c66affSColin Finck {
1391c2c66affSColin Finck mbedtls_mpi TB;
1392c2c66affSColin Finck int ret;
1393c2c66affSColin Finck size_t n;
1394292f67afSThomas Faber mbedtls_mpi_uint carry;
1395cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
1396cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL );
1397cbda039fSThomas Faber MPI_VALIDATE_RET( B != NULL );
1398c2c66affSColin Finck
1399c2c66affSColin Finck mbedtls_mpi_init( &TB );
1400c2c66affSColin Finck
1401c2c66affSColin Finck if( X == B )
1402c2c66affSColin Finck {
1403c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
1404c2c66affSColin Finck B = &TB;
1405c2c66affSColin Finck }
1406c2c66affSColin Finck
1407c2c66affSColin Finck if( X != A )
1408c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
1409c2c66affSColin Finck
1410c2c66affSColin Finck /*
1411c2c66affSColin Finck * X should always be positive as a result of unsigned subtractions.
1412c2c66affSColin Finck */
1413c2c66affSColin Finck X->s = 1;
1414c2c66affSColin Finck
1415c2c66affSColin Finck ret = 0;
1416c2c66affSColin Finck
1417c2c66affSColin Finck for( n = B->n; n > 0; n-- )
1418c2c66affSColin Finck if( B->p[n - 1] != 0 )
1419c2c66affSColin Finck break;
1420a01a8faaSThomas Faber if( n > A->n )
1421a01a8faaSThomas Faber {
1422a01a8faaSThomas Faber /* B >= (2^ciL)^n > A */
1423a01a8faaSThomas Faber ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1424a01a8faaSThomas Faber goto cleanup;
1425a01a8faaSThomas Faber }
1426c2c66affSColin Finck
1427292f67afSThomas Faber carry = mpi_sub_hlp( n, X->p, B->p );
1428292f67afSThomas Faber if( carry != 0 )
1429292f67afSThomas Faber {
1430292f67afSThomas Faber /* Propagate the carry to the first nonzero limb of X. */
1431292f67afSThomas Faber for( ; n < X->n && X->p[n] == 0; n++ )
1432292f67afSThomas Faber --X->p[n];
1433292f67afSThomas Faber /* If we ran out of space for the carry, it means that the result
1434292f67afSThomas Faber * is negative. */
1435292f67afSThomas Faber if( n == X->n )
14362e53fc8eSThomas Faber {
14372e53fc8eSThomas Faber ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
14382e53fc8eSThomas Faber goto cleanup;
14392e53fc8eSThomas Faber }
1440292f67afSThomas Faber --X->p[n];
1441292f67afSThomas Faber }
1442c2c66affSColin Finck
1443c2c66affSColin Finck cleanup:
1444c2c66affSColin Finck
1445c2c66affSColin Finck mbedtls_mpi_free( &TB );
1446c2c66affSColin Finck
1447c2c66affSColin Finck return( ret );
1448c2c66affSColin Finck }
1449c2c66affSColin Finck
1450c2c66affSColin Finck /*
1451c2c66affSColin Finck * Signed addition: X = A + B
1452c2c66affSColin Finck */
mbedtls_mpi_add_mpi(mbedtls_mpi * X,const mbedtls_mpi * A,const mbedtls_mpi * B)1453c2c66affSColin Finck int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1454c2c66affSColin Finck {
1455cbda039fSThomas Faber int ret, s;
1456cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
1457cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL );
1458cbda039fSThomas Faber MPI_VALIDATE_RET( B != NULL );
1459c2c66affSColin Finck
1460cbda039fSThomas Faber s = A->s;
1461c2c66affSColin Finck if( A->s * B->s < 0 )
1462c2c66affSColin Finck {
1463c2c66affSColin Finck if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
1464c2c66affSColin Finck {
1465c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
1466c2c66affSColin Finck X->s = s;
1467c2c66affSColin Finck }
1468c2c66affSColin Finck else
1469c2c66affSColin Finck {
1470c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
1471c2c66affSColin Finck X->s = -s;
1472c2c66affSColin Finck }
1473c2c66affSColin Finck }
1474c2c66affSColin Finck else
1475c2c66affSColin Finck {
1476c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
1477c2c66affSColin Finck X->s = s;
1478c2c66affSColin Finck }
1479c2c66affSColin Finck
1480c2c66affSColin Finck cleanup:
1481c2c66affSColin Finck
1482c2c66affSColin Finck return( ret );
1483c2c66affSColin Finck }
1484c2c66affSColin Finck
1485c2c66affSColin Finck /*
1486c2c66affSColin Finck * Signed subtraction: X = A - B
1487c2c66affSColin Finck */
mbedtls_mpi_sub_mpi(mbedtls_mpi * X,const mbedtls_mpi * A,const mbedtls_mpi * B)1488c2c66affSColin Finck int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1489c2c66affSColin Finck {
1490cbda039fSThomas Faber int ret, s;
1491cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
1492cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL );
1493cbda039fSThomas Faber MPI_VALIDATE_RET( B != NULL );
1494c2c66affSColin Finck
1495cbda039fSThomas Faber s = A->s;
1496c2c66affSColin Finck if( A->s * B->s > 0 )
1497c2c66affSColin Finck {
1498c2c66affSColin Finck if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
1499c2c66affSColin Finck {
1500c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
1501c2c66affSColin Finck X->s = s;
1502c2c66affSColin Finck }
1503c2c66affSColin Finck else
1504c2c66affSColin Finck {
1505c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
1506c2c66affSColin Finck X->s = -s;
1507c2c66affSColin Finck }
1508c2c66affSColin Finck }
1509c2c66affSColin Finck else
1510c2c66affSColin Finck {
1511c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
1512c2c66affSColin Finck X->s = s;
1513c2c66affSColin Finck }
1514c2c66affSColin Finck
1515c2c66affSColin Finck cleanup:
1516c2c66affSColin Finck
1517c2c66affSColin Finck return( ret );
1518c2c66affSColin Finck }
1519c2c66affSColin Finck
1520c2c66affSColin Finck /*
1521c2c66affSColin Finck * Signed addition: X = A + b
1522c2c66affSColin Finck */
mbedtls_mpi_add_int(mbedtls_mpi * X,const mbedtls_mpi * A,mbedtls_mpi_sint b)1523c2c66affSColin Finck int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1524c2c66affSColin Finck {
1525c2c66affSColin Finck mbedtls_mpi _B;
1526c2c66affSColin Finck mbedtls_mpi_uint p[1];
1527cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
1528cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL );
1529c2c66affSColin Finck
1530c2c66affSColin Finck p[0] = ( b < 0 ) ? -b : b;
1531c2c66affSColin Finck _B.s = ( b < 0 ) ? -1 : 1;
1532c2c66affSColin Finck _B.n = 1;
1533c2c66affSColin Finck _B.p = p;
1534c2c66affSColin Finck
1535c2c66affSColin Finck return( mbedtls_mpi_add_mpi( X, A, &_B ) );
1536c2c66affSColin Finck }
1537c2c66affSColin Finck
1538c2c66affSColin Finck /*
1539c2c66affSColin Finck * Signed subtraction: X = A - b
1540c2c66affSColin Finck */
mbedtls_mpi_sub_int(mbedtls_mpi * X,const mbedtls_mpi * A,mbedtls_mpi_sint b)1541c2c66affSColin Finck int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1542c2c66affSColin Finck {
1543c2c66affSColin Finck mbedtls_mpi _B;
1544c2c66affSColin Finck mbedtls_mpi_uint p[1];
1545cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
1546cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL );
1547c2c66affSColin Finck
1548c2c66affSColin Finck p[0] = ( b < 0 ) ? -b : b;
1549c2c66affSColin Finck _B.s = ( b < 0 ) ? -1 : 1;
1550c2c66affSColin Finck _B.n = 1;
1551c2c66affSColin Finck _B.p = p;
1552c2c66affSColin Finck
1553c2c66affSColin Finck return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
1554c2c66affSColin Finck }
1555c2c66affSColin Finck
1556c2c66affSColin Finck /*
1557c2c66affSColin Finck * Helper for mbedtls_mpi multiplication
1558c2c66affSColin Finck */
1559c2c66affSColin Finck static
1560c2c66affSColin Finck #if defined(__APPLE__) && defined(__arm__)
1561c2c66affSColin Finck /*
1562c2c66affSColin Finck * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1563c2c66affSColin Finck * appears to need this to prevent bad ARM code generation at -O3.
1564c2c66affSColin Finck */
1565c2c66affSColin Finck __attribute__ ((noinline))
1566c2c66affSColin Finck #endif
mpi_mul_hlp(size_t i,mbedtls_mpi_uint * s,mbedtls_mpi_uint * d,mbedtls_mpi_uint b)1567c2c66affSColin Finck void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b )
1568c2c66affSColin Finck {
1569c2c66affSColin Finck mbedtls_mpi_uint c = 0, t = 0;
1570c2c66affSColin Finck
1571c2c66affSColin Finck #if defined(MULADDC_HUIT)
1572c2c66affSColin Finck for( ; i >= 8; i -= 8 )
1573c2c66affSColin Finck {
1574c2c66affSColin Finck MULADDC_INIT
1575c2c66affSColin Finck MULADDC_HUIT
1576c2c66affSColin Finck MULADDC_STOP
1577c2c66affSColin Finck }
1578c2c66affSColin Finck
1579c2c66affSColin Finck for( ; i > 0; i-- )
1580c2c66affSColin Finck {
1581c2c66affSColin Finck MULADDC_INIT
1582c2c66affSColin Finck MULADDC_CORE
1583c2c66affSColin Finck MULADDC_STOP
1584c2c66affSColin Finck }
1585c2c66affSColin Finck #else /* MULADDC_HUIT */
1586c2c66affSColin Finck for( ; i >= 16; i -= 16 )
1587c2c66affSColin Finck {
1588c2c66affSColin Finck MULADDC_INIT
1589c2c66affSColin Finck MULADDC_CORE MULADDC_CORE
1590c2c66affSColin Finck MULADDC_CORE MULADDC_CORE
1591c2c66affSColin Finck MULADDC_CORE MULADDC_CORE
1592c2c66affSColin Finck MULADDC_CORE MULADDC_CORE
1593c2c66affSColin Finck
1594c2c66affSColin Finck MULADDC_CORE MULADDC_CORE
1595c2c66affSColin Finck MULADDC_CORE MULADDC_CORE
1596c2c66affSColin Finck MULADDC_CORE MULADDC_CORE
1597c2c66affSColin Finck MULADDC_CORE MULADDC_CORE
1598c2c66affSColin Finck MULADDC_STOP
1599c2c66affSColin Finck }
1600c2c66affSColin Finck
1601c2c66affSColin Finck for( ; i >= 8; i -= 8 )
1602c2c66affSColin Finck {
1603c2c66affSColin Finck MULADDC_INIT
1604c2c66affSColin Finck MULADDC_CORE MULADDC_CORE
1605c2c66affSColin Finck MULADDC_CORE MULADDC_CORE
1606c2c66affSColin Finck
1607c2c66affSColin Finck MULADDC_CORE MULADDC_CORE
1608c2c66affSColin Finck MULADDC_CORE MULADDC_CORE
1609c2c66affSColin Finck MULADDC_STOP
1610c2c66affSColin Finck }
1611c2c66affSColin Finck
1612c2c66affSColin Finck for( ; i > 0; i-- )
1613c2c66affSColin Finck {
1614c2c66affSColin Finck MULADDC_INIT
1615c2c66affSColin Finck MULADDC_CORE
1616c2c66affSColin Finck MULADDC_STOP
1617c2c66affSColin Finck }
1618c2c66affSColin Finck #endif /* MULADDC_HUIT */
1619c2c66affSColin Finck
1620c2c66affSColin Finck t++;
1621c2c66affSColin Finck
1622c2c66affSColin Finck do {
1623c2c66affSColin Finck *d += c; c = ( *d < c ); d++;
1624c2c66affSColin Finck }
1625c2c66affSColin Finck while( c != 0 );
1626c2c66affSColin Finck }
1627c2c66affSColin Finck
1628c2c66affSColin Finck /*
1629c2c66affSColin Finck * Baseline multiplication: X = A * B (HAC 14.12)
1630c2c66affSColin Finck */
mbedtls_mpi_mul_mpi(mbedtls_mpi * X,const mbedtls_mpi * A,const mbedtls_mpi * B)1631c2c66affSColin Finck int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1632c2c66affSColin Finck {
1633c2c66affSColin Finck int ret;
1634c2c66affSColin Finck size_t i, j;
1635c2c66affSColin Finck mbedtls_mpi TA, TB;
1636*103a79ceSThomas Faber int result_is_zero = 0;
1637cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
1638cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL );
1639cbda039fSThomas Faber MPI_VALIDATE_RET( B != NULL );
1640c2c66affSColin Finck
1641c2c66affSColin Finck mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
1642c2c66affSColin Finck
1643c2c66affSColin Finck if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1644c2c66affSColin Finck if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
1645c2c66affSColin Finck
1646c2c66affSColin Finck for( i = A->n; i > 0; i-- )
1647c2c66affSColin Finck if( A->p[i - 1] != 0 )
1648c2c66affSColin Finck break;
1649*103a79ceSThomas Faber if( i == 0 )
1650*103a79ceSThomas Faber result_is_zero = 1;
1651c2c66affSColin Finck
1652c2c66affSColin Finck for( j = B->n; j > 0; j-- )
1653c2c66affSColin Finck if( B->p[j - 1] != 0 )
1654c2c66affSColin Finck break;
1655*103a79ceSThomas Faber if( j == 0 )
1656*103a79ceSThomas Faber result_is_zero = 1;
1657c2c66affSColin Finck
1658c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1659c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
1660c2c66affSColin Finck
1661cbda039fSThomas Faber for( ; j > 0; j-- )
1662cbda039fSThomas Faber mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
1663c2c66affSColin Finck
1664*103a79ceSThomas Faber /* If the result is 0, we don't shortcut the operation, which reduces
1665*103a79ceSThomas Faber * but does not eliminate side channels leaking the zero-ness. We do
1666*103a79ceSThomas Faber * need to take care to set the sign bit properly since the library does
1667*103a79ceSThomas Faber * not fully support an MPI object with a value of 0 and s == -1. */
1668*103a79ceSThomas Faber if( result_is_zero )
1669*103a79ceSThomas Faber X->s = 1;
1670*103a79ceSThomas Faber else
1671c2c66affSColin Finck X->s = A->s * B->s;
1672c2c66affSColin Finck
1673c2c66affSColin Finck cleanup:
1674c2c66affSColin Finck
1675c2c66affSColin Finck mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
1676c2c66affSColin Finck
1677c2c66affSColin Finck return( ret );
1678c2c66affSColin Finck }
1679c2c66affSColin Finck
1680c2c66affSColin Finck /*
1681c2c66affSColin Finck * Baseline multiplication: X = A * b
1682c2c66affSColin Finck */
mbedtls_mpi_mul_int(mbedtls_mpi * X,const mbedtls_mpi * A,mbedtls_mpi_uint b)1683c2c66affSColin Finck int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
1684c2c66affSColin Finck {
1685c2c66affSColin Finck mbedtls_mpi _B;
1686c2c66affSColin Finck mbedtls_mpi_uint p[1];
1687cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
1688cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL );
1689c2c66affSColin Finck
1690c2c66affSColin Finck _B.s = 1;
1691c2c66affSColin Finck _B.n = 1;
1692c2c66affSColin Finck _B.p = p;
1693c2c66affSColin Finck p[0] = b;
1694c2c66affSColin Finck
1695c2c66affSColin Finck return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
1696c2c66affSColin Finck }
1697c2c66affSColin Finck
1698c2c66affSColin Finck /*
1699c2c66affSColin Finck * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1700c2c66affSColin Finck * mbedtls_mpi_uint divisor, d
1701c2c66affSColin Finck */
mbedtls_int_div_int(mbedtls_mpi_uint u1,mbedtls_mpi_uint u0,mbedtls_mpi_uint d,mbedtls_mpi_uint * r)1702c2c66affSColin Finck static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1703c2c66affSColin Finck mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
1704c2c66affSColin Finck {
1705c2c66affSColin Finck #if defined(MBEDTLS_HAVE_UDBL)
1706c2c66affSColin Finck mbedtls_t_udbl dividend, quotient;
1707c2c66affSColin Finck #else
1708c2c66affSColin Finck const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1709c2c66affSColin Finck const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
1710c2c66affSColin Finck mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1711c2c66affSColin Finck mbedtls_mpi_uint u0_msw, u0_lsw;
1712c2c66affSColin Finck size_t s;
1713c2c66affSColin Finck #endif
1714c2c66affSColin Finck
1715c2c66affSColin Finck /*
1716c2c66affSColin Finck * Check for overflow
1717c2c66affSColin Finck */
1718c2c66affSColin Finck if( 0 == d || u1 >= d )
1719c2c66affSColin Finck {
1720c2c66affSColin Finck if (r != NULL) *r = ~0;
1721c2c66affSColin Finck
1722c2c66affSColin Finck return ( ~0 );
1723c2c66affSColin Finck }
1724c2c66affSColin Finck
1725c2c66affSColin Finck #if defined(MBEDTLS_HAVE_UDBL)
1726c2c66affSColin Finck dividend = (mbedtls_t_udbl) u1 << biL;
1727c2c66affSColin Finck dividend |= (mbedtls_t_udbl) u0;
1728c2c66affSColin Finck quotient = dividend / d;
1729c2c66affSColin Finck if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1730c2c66affSColin Finck quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1731c2c66affSColin Finck
1732c2c66affSColin Finck if( r != NULL )
1733c2c66affSColin Finck *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
1734c2c66affSColin Finck
1735c2c66affSColin Finck return (mbedtls_mpi_uint) quotient;
1736c2c66affSColin Finck #else
1737c2c66affSColin Finck
1738c2c66affSColin Finck /*
1739c2c66affSColin Finck * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1740c2c66affSColin Finck * Vol. 2 - Seminumerical Algorithms, Knuth
1741c2c66affSColin Finck */
1742c2c66affSColin Finck
1743c2c66affSColin Finck /*
1744c2c66affSColin Finck * Normalize the divisor, d, and dividend, u0, u1
1745c2c66affSColin Finck */
1746c2c66affSColin Finck s = mbedtls_clz( d );
1747c2c66affSColin Finck d = d << s;
1748c2c66affSColin Finck
1749c2c66affSColin Finck u1 = u1 << s;
1750c2c66affSColin Finck u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
1751c2c66affSColin Finck u0 = u0 << s;
1752c2c66affSColin Finck
1753c2c66affSColin Finck d1 = d >> biH;
1754c2c66affSColin Finck d0 = d & uint_halfword_mask;
1755c2c66affSColin Finck
1756c2c66affSColin Finck u0_msw = u0 >> biH;
1757c2c66affSColin Finck u0_lsw = u0 & uint_halfword_mask;
1758c2c66affSColin Finck
1759c2c66affSColin Finck /*
1760c2c66affSColin Finck * Find the first quotient and remainder
1761c2c66affSColin Finck */
1762c2c66affSColin Finck q1 = u1 / d1;
1763c2c66affSColin Finck r0 = u1 - d1 * q1;
1764c2c66affSColin Finck
1765c2c66affSColin Finck while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1766c2c66affSColin Finck {
1767c2c66affSColin Finck q1 -= 1;
1768c2c66affSColin Finck r0 += d1;
1769c2c66affSColin Finck
1770c2c66affSColin Finck if ( r0 >= radix ) break;
1771c2c66affSColin Finck }
1772c2c66affSColin Finck
1773c2c66affSColin Finck rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
1774c2c66affSColin Finck q0 = rAX / d1;
1775c2c66affSColin Finck r0 = rAX - q0 * d1;
1776c2c66affSColin Finck
1777c2c66affSColin Finck while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1778c2c66affSColin Finck {
1779c2c66affSColin Finck q0 -= 1;
1780c2c66affSColin Finck r0 += d1;
1781c2c66affSColin Finck
1782c2c66affSColin Finck if ( r0 >= radix ) break;
1783c2c66affSColin Finck }
1784c2c66affSColin Finck
1785c2c66affSColin Finck if (r != NULL)
1786c2c66affSColin Finck *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
1787c2c66affSColin Finck
1788c2c66affSColin Finck quotient = q1 * radix + q0;
1789c2c66affSColin Finck
1790c2c66affSColin Finck return quotient;
1791c2c66affSColin Finck #endif
1792c2c66affSColin Finck }
1793c2c66affSColin Finck
1794c2c66affSColin Finck /*
1795c2c66affSColin Finck * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
1796c2c66affSColin Finck */
mbedtls_mpi_div_mpi(mbedtls_mpi * Q,mbedtls_mpi * R,const mbedtls_mpi * A,const mbedtls_mpi * B)1797cbda039fSThomas Faber int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1798cbda039fSThomas Faber const mbedtls_mpi *B )
1799c2c66affSColin Finck {
1800c2c66affSColin Finck int ret;
1801c2c66affSColin Finck size_t i, n, t, k;
1802c2c66affSColin Finck mbedtls_mpi X, Y, Z, T1, T2;
1803cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL );
1804cbda039fSThomas Faber MPI_VALIDATE_RET( B != NULL );
1805c2c66affSColin Finck
1806c2c66affSColin Finck if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1807c2c66affSColin Finck return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
1808c2c66affSColin Finck
1809c2c66affSColin Finck mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1810c2c66affSColin Finck mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
1811c2c66affSColin Finck
1812c2c66affSColin Finck if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1813c2c66affSColin Finck {
1814c2c66affSColin Finck if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1815c2c66affSColin Finck if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
1816c2c66affSColin Finck return( 0 );
1817c2c66affSColin Finck }
1818c2c66affSColin Finck
1819c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1820c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
1821c2c66affSColin Finck X.s = Y.s = 1;
1822c2c66affSColin Finck
1823c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1824c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1825c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1826c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
1827c2c66affSColin Finck
1828c2c66affSColin Finck k = mbedtls_mpi_bitlen( &Y ) % biL;
1829c2c66affSColin Finck if( k < biL - 1 )
1830c2c66affSColin Finck {
1831c2c66affSColin Finck k = biL - 1 - k;
1832c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1833c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
1834c2c66affSColin Finck }
1835c2c66affSColin Finck else k = 0;
1836c2c66affSColin Finck
1837c2c66affSColin Finck n = X.n - 1;
1838c2c66affSColin Finck t = Y.n - 1;
1839c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
1840c2c66affSColin Finck
1841c2c66affSColin Finck while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
1842c2c66affSColin Finck {
1843c2c66affSColin Finck Z.p[n - t]++;
1844c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
1845c2c66affSColin Finck }
1846c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
1847c2c66affSColin Finck
1848c2c66affSColin Finck for( i = n; i > t ; i-- )
1849c2c66affSColin Finck {
1850c2c66affSColin Finck if( X.p[i] >= Y.p[t] )
1851c2c66affSColin Finck Z.p[i - t - 1] = ~0;
1852c2c66affSColin Finck else
1853c2c66affSColin Finck {
1854c2c66affSColin Finck Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1855c2c66affSColin Finck Y.p[t], NULL);
1856c2c66affSColin Finck }
1857c2c66affSColin Finck
1858c2c66affSColin Finck Z.p[i - t - 1]++;
1859c2c66affSColin Finck do
1860c2c66affSColin Finck {
1861c2c66affSColin Finck Z.p[i - t - 1]--;
1862c2c66affSColin Finck
1863c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
1864c2c66affSColin Finck T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
1865c2c66affSColin Finck T1.p[1] = Y.p[t];
1866c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1867c2c66affSColin Finck
1868c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
1869c2c66affSColin Finck T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1870c2c66affSColin Finck T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1871c2c66affSColin Finck T2.p[2] = X.p[i];
1872c2c66affSColin Finck }
1873c2c66affSColin Finck while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
1874c2c66affSColin Finck
1875c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1876c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1877c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
1878c2c66affSColin Finck
1879c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
1880c2c66affSColin Finck {
1881c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1882c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1883c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
1884c2c66affSColin Finck Z.p[i - t - 1]--;
1885c2c66affSColin Finck }
1886c2c66affSColin Finck }
1887c2c66affSColin Finck
1888c2c66affSColin Finck if( Q != NULL )
1889c2c66affSColin Finck {
1890c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
1891c2c66affSColin Finck Q->s = A->s * B->s;
1892c2c66affSColin Finck }
1893c2c66affSColin Finck
1894c2c66affSColin Finck if( R != NULL )
1895c2c66affSColin Finck {
1896c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
1897c2c66affSColin Finck X.s = A->s;
1898c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
1899c2c66affSColin Finck
1900c2c66affSColin Finck if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
1901c2c66affSColin Finck R->s = 1;
1902c2c66affSColin Finck }
1903c2c66affSColin Finck
1904c2c66affSColin Finck cleanup:
1905c2c66affSColin Finck
1906c2c66affSColin Finck mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1907c2c66affSColin Finck mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
1908c2c66affSColin Finck
1909c2c66affSColin Finck return( ret );
1910c2c66affSColin Finck }
1911c2c66affSColin Finck
1912c2c66affSColin Finck /*
1913c2c66affSColin Finck * Division by int: A = Q * b + R
1914c2c66affSColin Finck */
mbedtls_mpi_div_int(mbedtls_mpi * Q,mbedtls_mpi * R,const mbedtls_mpi * A,mbedtls_mpi_sint b)1915cbda039fSThomas Faber int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1916cbda039fSThomas Faber const mbedtls_mpi *A,
1917cbda039fSThomas Faber mbedtls_mpi_sint b )
1918c2c66affSColin Finck {
1919c2c66affSColin Finck mbedtls_mpi _B;
1920c2c66affSColin Finck mbedtls_mpi_uint p[1];
1921cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL );
1922c2c66affSColin Finck
1923c2c66affSColin Finck p[0] = ( b < 0 ) ? -b : b;
1924c2c66affSColin Finck _B.s = ( b < 0 ) ? -1 : 1;
1925c2c66affSColin Finck _B.n = 1;
1926c2c66affSColin Finck _B.p = p;
1927c2c66affSColin Finck
1928c2c66affSColin Finck return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
1929c2c66affSColin Finck }
1930c2c66affSColin Finck
1931c2c66affSColin Finck /*
1932c2c66affSColin Finck * Modulo: R = A mod B
1933c2c66affSColin Finck */
mbedtls_mpi_mod_mpi(mbedtls_mpi * R,const mbedtls_mpi * A,const mbedtls_mpi * B)1934c2c66affSColin Finck int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
1935c2c66affSColin Finck {
1936c2c66affSColin Finck int ret;
1937cbda039fSThomas Faber MPI_VALIDATE_RET( R != NULL );
1938cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL );
1939cbda039fSThomas Faber MPI_VALIDATE_RET( B != NULL );
1940c2c66affSColin Finck
1941c2c66affSColin Finck if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1942c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
1943c2c66affSColin Finck
1944c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
1945c2c66affSColin Finck
1946c2c66affSColin Finck while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1947c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
1948c2c66affSColin Finck
1949c2c66affSColin Finck while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1950c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
1951c2c66affSColin Finck
1952c2c66affSColin Finck cleanup:
1953c2c66affSColin Finck
1954c2c66affSColin Finck return( ret );
1955c2c66affSColin Finck }
1956c2c66affSColin Finck
1957c2c66affSColin Finck /*
1958c2c66affSColin Finck * Modulo: r = A mod b
1959c2c66affSColin Finck */
mbedtls_mpi_mod_int(mbedtls_mpi_uint * r,const mbedtls_mpi * A,mbedtls_mpi_sint b)1960c2c66affSColin Finck int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1961c2c66affSColin Finck {
1962c2c66affSColin Finck size_t i;
1963c2c66affSColin Finck mbedtls_mpi_uint x, y, z;
1964cbda039fSThomas Faber MPI_VALIDATE_RET( r != NULL );
1965cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL );
1966c2c66affSColin Finck
1967c2c66affSColin Finck if( b == 0 )
1968c2c66affSColin Finck return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
1969c2c66affSColin Finck
1970c2c66affSColin Finck if( b < 0 )
1971c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
1972c2c66affSColin Finck
1973c2c66affSColin Finck /*
1974c2c66affSColin Finck * handle trivial cases
1975c2c66affSColin Finck */
1976c2c66affSColin Finck if( b == 1 )
1977c2c66affSColin Finck {
1978c2c66affSColin Finck *r = 0;
1979c2c66affSColin Finck return( 0 );
1980c2c66affSColin Finck }
1981c2c66affSColin Finck
1982c2c66affSColin Finck if( b == 2 )
1983c2c66affSColin Finck {
1984c2c66affSColin Finck *r = A->p[0] & 1;
1985c2c66affSColin Finck return( 0 );
1986c2c66affSColin Finck }
1987c2c66affSColin Finck
1988c2c66affSColin Finck /*
1989c2c66affSColin Finck * general case
1990c2c66affSColin Finck */
1991c2c66affSColin Finck for( i = A->n, y = 0; i > 0; i-- )
1992c2c66affSColin Finck {
1993c2c66affSColin Finck x = A->p[i - 1];
1994c2c66affSColin Finck y = ( y << biH ) | ( x >> biH );
1995c2c66affSColin Finck z = y / b;
1996c2c66affSColin Finck y -= z * b;
1997c2c66affSColin Finck
1998c2c66affSColin Finck x <<= biH;
1999c2c66affSColin Finck y = ( y << biH ) | ( x >> biH );
2000c2c66affSColin Finck z = y / b;
2001c2c66affSColin Finck y -= z * b;
2002c2c66affSColin Finck }
2003c2c66affSColin Finck
2004c2c66affSColin Finck /*
2005c2c66affSColin Finck * If A is negative, then the current y represents a negative value.
2006c2c66affSColin Finck * Flipping it to the positive side.
2007c2c66affSColin Finck */
2008c2c66affSColin Finck if( A->s < 0 && y != 0 )
2009c2c66affSColin Finck y = b - y;
2010c2c66affSColin Finck
2011c2c66affSColin Finck *r = y;
2012c2c66affSColin Finck
2013c2c66affSColin Finck return( 0 );
2014c2c66affSColin Finck }
2015c2c66affSColin Finck
2016c2c66affSColin Finck /*
2017c2c66affSColin Finck * Fast Montgomery initialization (thanks to Tom St Denis)
2018c2c66affSColin Finck */
mpi_montg_init(mbedtls_mpi_uint * mm,const mbedtls_mpi * N)2019c2c66affSColin Finck static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
2020c2c66affSColin Finck {
2021c2c66affSColin Finck mbedtls_mpi_uint x, m0 = N->p[0];
2022c2c66affSColin Finck unsigned int i;
2023c2c66affSColin Finck
2024c2c66affSColin Finck x = m0;
2025c2c66affSColin Finck x += ( ( m0 + 2 ) & 4 ) << 1;
2026c2c66affSColin Finck
2027c2c66affSColin Finck for( i = biL; i >= 8; i /= 2 )
2028c2c66affSColin Finck x *= ( 2 - ( m0 * x ) );
2029c2c66affSColin Finck
2030c2c66affSColin Finck *mm = ~x + 1;
2031c2c66affSColin Finck }
2032c2c66affSColin Finck
2033292f67afSThomas Faber /** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
2034292f67afSThomas Faber *
2035292f67afSThomas Faber * \param[in,out] A One of the numbers to multiply.
2036292f67afSThomas Faber * It must have at least as many limbs as N
2037292f67afSThomas Faber * (A->n >= N->n), and any limbs beyond n are ignored.
2038292f67afSThomas Faber * On successful completion, A contains the result of
2039292f67afSThomas Faber * the multiplication A * B * R^-1 mod N where
2040292f67afSThomas Faber * R = (2^ciL)^n.
2041292f67afSThomas Faber * \param[in] B One of the numbers to multiply.
2042292f67afSThomas Faber * It must be nonzero and must not have more limbs than N
2043292f67afSThomas Faber * (B->n <= N->n).
2044292f67afSThomas Faber * \param[in] N The modulo. N must be odd.
2045292f67afSThomas Faber * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
2046292f67afSThomas Faber * This is -N^-1 mod 2^ciL.
2047292f67afSThomas Faber * \param[in,out] T A bignum for temporary storage.
2048292f67afSThomas Faber * It must be at least twice the limb size of N plus 2
2049292f67afSThomas Faber * (T->n >= 2 * (N->n + 1)).
2050292f67afSThomas Faber * Its initial content is unused and
2051292f67afSThomas Faber * its final content is indeterminate.
2052292f67afSThomas Faber * Note that unlike the usual convention in the library
2053292f67afSThomas Faber * for `const mbedtls_mpi*`, the content of T can change.
2054c2c66affSColin Finck */
mpi_montmul(mbedtls_mpi * A,const mbedtls_mpi * B,const mbedtls_mpi * N,mbedtls_mpi_uint mm,const mbedtls_mpi * T)2055292f67afSThomas Faber static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
2056c2c66affSColin Finck const mbedtls_mpi *T )
2057c2c66affSColin Finck {
2058c2c66affSColin Finck size_t i, n, m;
2059c2c66affSColin Finck mbedtls_mpi_uint u0, u1, *d;
2060c2c66affSColin Finck
2061c2c66affSColin Finck memset( T->p, 0, T->n * ciL );
2062c2c66affSColin Finck
2063c2c66affSColin Finck d = T->p;
2064c2c66affSColin Finck n = N->n;
2065c2c66affSColin Finck m = ( B->n < n ) ? B->n : n;
2066c2c66affSColin Finck
2067c2c66affSColin Finck for( i = 0; i < n; i++ )
2068c2c66affSColin Finck {
2069c2c66affSColin Finck /*
2070c2c66affSColin Finck * T = (T + u0*B + u1*N) / 2^biL
2071c2c66affSColin Finck */
2072c2c66affSColin Finck u0 = A->p[i];
2073c2c66affSColin Finck u1 = ( d[0] + u0 * B->p[0] ) * mm;
2074c2c66affSColin Finck
2075c2c66affSColin Finck mpi_mul_hlp( m, B->p, d, u0 );
2076c2c66affSColin Finck mpi_mul_hlp( n, N->p, d, u1 );
2077c2c66affSColin Finck
2078c2c66affSColin Finck *d++ = u0; d[n + 1] = 0;
2079c2c66affSColin Finck }
2080c2c66affSColin Finck
2081292f67afSThomas Faber /* At this point, d is either the desired result or the desired result
2082292f67afSThomas Faber * plus N. We now potentially subtract N, avoiding leaking whether the
2083292f67afSThomas Faber * subtraction is performed through side channels. */
2084c2c66affSColin Finck
2085292f67afSThomas Faber /* Copy the n least significant limbs of d to A, so that
2086292f67afSThomas Faber * A = d if d < N (recall that N has n limbs). */
2087292f67afSThomas Faber memcpy( A->p, d, n * ciL );
2088292f67afSThomas Faber /* If d >= N then we want to set A to d - N. To prevent timing attacks,
2089292f67afSThomas Faber * do the calculation without using conditional tests. */
2090292f67afSThomas Faber /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
2091292f67afSThomas Faber d[n] += 1;
2092292f67afSThomas Faber d[n] -= mpi_sub_hlp( n, d, N->p );
2093292f67afSThomas Faber /* If d0 < N then d < (2^biL)^n
2094292f67afSThomas Faber * so d[n] == 0 and we want to keep A as it is.
2095292f67afSThomas Faber * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2096292f67afSThomas Faber * so d[n] == 1 and we want to set A to the result of the subtraction
2097292f67afSThomas Faber * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2098292f67afSThomas Faber * This exactly corresponds to a conditional assignment. */
2099292f67afSThomas Faber mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
2100c2c66affSColin Finck }
2101c2c66affSColin Finck
2102c2c66affSColin Finck /*
2103c2c66affSColin Finck * Montgomery reduction: A = A * R^-1 mod N
2104292f67afSThomas Faber *
2105292f67afSThomas Faber * See mpi_montmul() regarding constraints and guarantees on the parameters.
2106c2c66affSColin Finck */
mpi_montred(mbedtls_mpi * A,const mbedtls_mpi * N,mbedtls_mpi_uint mm,const mbedtls_mpi * T)2107cbda039fSThomas Faber static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
2108cbda039fSThomas Faber mbedtls_mpi_uint mm, const mbedtls_mpi *T )
2109c2c66affSColin Finck {
2110c2c66affSColin Finck mbedtls_mpi_uint z = 1;
2111c2c66affSColin Finck mbedtls_mpi U;
2112c2c66affSColin Finck
2113c2c66affSColin Finck U.n = U.s = (int) z;
2114c2c66affSColin Finck U.p = &z;
2115c2c66affSColin Finck
2116292f67afSThomas Faber mpi_montmul( A, &U, N, mm, T );
2117c2c66affSColin Finck }
2118c2c66affSColin Finck
2119c2c66affSColin Finck /*
2120*103a79ceSThomas Faber * Constant-flow boolean "equal" comparison:
2121*103a79ceSThomas Faber * return x == y
2122*103a79ceSThomas Faber *
2123*103a79ceSThomas Faber * This function can be used to write constant-time code by replacing branches
2124*103a79ceSThomas Faber * with bit operations - it can be used in conjunction with
2125*103a79ceSThomas Faber * mbedtls_ssl_cf_mask_from_bit().
2126*103a79ceSThomas Faber *
2127*103a79ceSThomas Faber * This function is implemented without using comparison operators, as those
2128*103a79ceSThomas Faber * might be translated to branches by some compilers on some platforms.
2129*103a79ceSThomas Faber */
mbedtls_mpi_cf_bool_eq(size_t x,size_t y)2130*103a79ceSThomas Faber static size_t mbedtls_mpi_cf_bool_eq( size_t x, size_t y )
2131*103a79ceSThomas Faber {
2132*103a79ceSThomas Faber /* diff = 0 if x == y, non-zero otherwise */
2133*103a79ceSThomas Faber const size_t diff = x ^ y;
2134*103a79ceSThomas Faber
2135*103a79ceSThomas Faber /* MSVC has a warning about unary minus on unsigned integer types,
2136*103a79ceSThomas Faber * but this is well-defined and precisely what we want to do here. */
2137*103a79ceSThomas Faber #if defined(_MSC_VER)
2138*103a79ceSThomas Faber #pragma warning( push )
2139*103a79ceSThomas Faber #pragma warning( disable : 4146 )
2140*103a79ceSThomas Faber #endif
2141*103a79ceSThomas Faber
2142*103a79ceSThomas Faber /* diff_msb's most significant bit is equal to x != y */
2143*103a79ceSThomas Faber const size_t diff_msb = ( diff | (size_t) -diff );
2144*103a79ceSThomas Faber
2145*103a79ceSThomas Faber #if defined(_MSC_VER)
2146*103a79ceSThomas Faber #pragma warning( pop )
2147*103a79ceSThomas Faber #endif
2148*103a79ceSThomas Faber
2149*103a79ceSThomas Faber /* diff1 = (x != y) ? 1 : 0 */
2150*103a79ceSThomas Faber const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 );
2151*103a79ceSThomas Faber
2152*103a79ceSThomas Faber return( 1 ^ diff1 );
2153*103a79ceSThomas Faber }
2154*103a79ceSThomas Faber
2155*103a79ceSThomas Faber /**
2156*103a79ceSThomas Faber * Select an MPI from a table without leaking the index.
2157*103a79ceSThomas Faber *
2158*103a79ceSThomas Faber * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
2159*103a79ceSThomas Faber * reads the entire table in order to avoid leaking the value of idx to an
2160*103a79ceSThomas Faber * attacker able to observe memory access patterns.
2161*103a79ceSThomas Faber *
2162*103a79ceSThomas Faber * \param[out] R Where to write the selected MPI.
2163*103a79ceSThomas Faber * \param[in] T The table to read from.
2164*103a79ceSThomas Faber * \param[in] T_size The number of elements in the table.
2165*103a79ceSThomas Faber * \param[in] idx The index of the element to select;
2166*103a79ceSThomas Faber * this must satisfy 0 <= idx < T_size.
2167*103a79ceSThomas Faber *
2168*103a79ceSThomas Faber * \return \c 0 on success, or a negative error code.
2169*103a79ceSThomas Faber */
mpi_select(mbedtls_mpi * R,const mbedtls_mpi * T,size_t T_size,size_t idx)2170*103a79ceSThomas Faber static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
2171*103a79ceSThomas Faber {
2172*103a79ceSThomas Faber int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2173*103a79ceSThomas Faber size_t i;
2174*103a79ceSThomas Faber
2175*103a79ceSThomas Faber for( i = 0; i < T_size; i++ )
2176*103a79ceSThomas Faber {
2177*103a79ceSThomas Faber MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
2178*103a79ceSThomas Faber (unsigned char) mbedtls_mpi_cf_bool_eq( i, idx ) ) );
2179*103a79ceSThomas Faber }
2180*103a79ceSThomas Faber
2181*103a79ceSThomas Faber cleanup:
2182*103a79ceSThomas Faber return( ret );
2183*103a79ceSThomas Faber }
2184*103a79ceSThomas Faber
2185*103a79ceSThomas Faber /*
2186c2c66affSColin Finck * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2187c2c66affSColin Finck */
mbedtls_mpi_exp_mod(mbedtls_mpi * X,const mbedtls_mpi * A,const mbedtls_mpi * E,const mbedtls_mpi * N,mbedtls_mpi * _RR)2188cbda039fSThomas Faber int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2189cbda039fSThomas Faber const mbedtls_mpi *E, const mbedtls_mpi *N,
2190cbda039fSThomas Faber mbedtls_mpi *_RR )
2191c2c66affSColin Finck {
2192c2c66affSColin Finck int ret;
2193c2c66affSColin Finck size_t wbits, wsize, one = 1;
2194c2c66affSColin Finck size_t i, j, nblimbs;
2195c2c66affSColin Finck size_t bufsize, nbits;
2196c2c66affSColin Finck mbedtls_mpi_uint ei, mm, state;
2197*103a79ceSThomas Faber mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
2198c2c66affSColin Finck int neg;
2199c2c66affSColin Finck
2200cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
2201cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL );
2202cbda039fSThomas Faber MPI_VALIDATE_RET( E != NULL );
2203cbda039fSThomas Faber MPI_VALIDATE_RET( N != NULL );
2204cbda039fSThomas Faber
2205d9e6c9b5SThomas Faber if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
2206c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2207c2c66affSColin Finck
2208c2c66affSColin Finck if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2209c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2210c2c66affSColin Finck
22112e53fc8eSThomas Faber if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
22122e53fc8eSThomas Faber mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
22132e53fc8eSThomas Faber return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
22142e53fc8eSThomas Faber
2215c2c66affSColin Finck /*
2216c2c66affSColin Finck * Init temps and window size
2217c2c66affSColin Finck */
2218c2c66affSColin Finck mpi_montg_init( &mm, N );
2219c2c66affSColin Finck mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2220c2c66affSColin Finck mbedtls_mpi_init( &Apos );
2221*103a79ceSThomas Faber mbedtls_mpi_init( &WW );
2222c2c66affSColin Finck memset( W, 0, sizeof( W ) );
2223c2c66affSColin Finck
2224c2c66affSColin Finck i = mbedtls_mpi_bitlen( E );
2225c2c66affSColin Finck
2226c2c66affSColin Finck wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2227c2c66affSColin Finck ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2228c2c66affSColin Finck
2229430656f0SThomas Faber #if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
2230c2c66affSColin Finck if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2231c2c66affSColin Finck wsize = MBEDTLS_MPI_WINDOW_SIZE;
2232430656f0SThomas Faber #endif
2233c2c66affSColin Finck
2234c2c66affSColin Finck j = N->n + 1;
2235*103a79ceSThomas Faber /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
2236*103a79ceSThomas Faber * and mpi_montred() calls later. Here we ensure that W[1] and X are
2237*103a79ceSThomas Faber * large enough, and later we'll grow other W[i] to the same length.
2238*103a79ceSThomas Faber * They must not be shrunk midway through this function!
2239*103a79ceSThomas Faber */
2240c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2241c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2242c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
2243c2c66affSColin Finck
2244c2c66affSColin Finck /*
2245c2c66affSColin Finck * Compensate for negative A (and correct at the end)
2246c2c66affSColin Finck */
2247c2c66affSColin Finck neg = ( A->s == -1 );
2248c2c66affSColin Finck if( neg )
2249c2c66affSColin Finck {
2250c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
2251c2c66affSColin Finck Apos.s = 1;
2252c2c66affSColin Finck A = &Apos;
2253c2c66affSColin Finck }
2254c2c66affSColin Finck
2255c2c66affSColin Finck /*
2256c2c66affSColin Finck * If 1st call, pre-compute R^2 mod N
2257c2c66affSColin Finck */
2258c2c66affSColin Finck if( _RR == NULL || _RR->p == NULL )
2259c2c66affSColin Finck {
2260c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2261c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2262c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
2263c2c66affSColin Finck
2264c2c66affSColin Finck if( _RR != NULL )
2265c2c66affSColin Finck memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
2266c2c66affSColin Finck }
2267c2c66affSColin Finck else
2268c2c66affSColin Finck memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
2269c2c66affSColin Finck
2270c2c66affSColin Finck /*
2271c2c66affSColin Finck * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2272c2c66affSColin Finck */
2273c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2274c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
2275c2c66affSColin Finck else
2276c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
2277*103a79ceSThomas Faber /* Re-grow W[1] if necessary. This should be only necessary in one corner
2278*103a79ceSThomas Faber * case: when A == 0 represented with A.n == 0, mbedtls_mpi_copy shrinks
2279*103a79ceSThomas Faber * W[1] to 0 limbs. */
2280*103a79ceSThomas Faber MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], N->n +1 ) );
2281c2c66affSColin Finck
2282292f67afSThomas Faber mpi_montmul( &W[1], &RR, N, mm, &T );
2283c2c66affSColin Finck
2284c2c66affSColin Finck /*
2285c2c66affSColin Finck * X = R^2 * R^-1 mod N = R mod N
2286c2c66affSColin Finck */
2287c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
2288292f67afSThomas Faber mpi_montred( X, N, mm, &T );
2289c2c66affSColin Finck
2290c2c66affSColin Finck if( wsize > 1 )
2291c2c66affSColin Finck {
2292c2c66affSColin Finck /*
2293c2c66affSColin Finck * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2294c2c66affSColin Finck */
2295c2c66affSColin Finck j = one << ( wsize - 1 );
2296c2c66affSColin Finck
2297c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2298c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
2299c2c66affSColin Finck
2300c2c66affSColin Finck for( i = 0; i < wsize - 1; i++ )
2301292f67afSThomas Faber mpi_montmul( &W[j], &W[j], N, mm, &T );
2302c2c66affSColin Finck
2303c2c66affSColin Finck /*
2304c2c66affSColin Finck * W[i] = W[i - 1] * W[1]
2305c2c66affSColin Finck */
2306c2c66affSColin Finck for( i = j + 1; i < ( one << wsize ); i++ )
2307c2c66affSColin Finck {
2308c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2309c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
2310c2c66affSColin Finck
2311292f67afSThomas Faber mpi_montmul( &W[i], &W[1], N, mm, &T );
2312c2c66affSColin Finck }
2313c2c66affSColin Finck }
2314c2c66affSColin Finck
2315c2c66affSColin Finck nblimbs = E->n;
2316c2c66affSColin Finck bufsize = 0;
2317c2c66affSColin Finck nbits = 0;
2318c2c66affSColin Finck wbits = 0;
2319c2c66affSColin Finck state = 0;
2320c2c66affSColin Finck
2321c2c66affSColin Finck while( 1 )
2322c2c66affSColin Finck {
2323c2c66affSColin Finck if( bufsize == 0 )
2324c2c66affSColin Finck {
2325c2c66affSColin Finck if( nblimbs == 0 )
2326c2c66affSColin Finck break;
2327c2c66affSColin Finck
2328c2c66affSColin Finck nblimbs--;
2329c2c66affSColin Finck
2330c2c66affSColin Finck bufsize = sizeof( mbedtls_mpi_uint ) << 3;
2331c2c66affSColin Finck }
2332c2c66affSColin Finck
2333c2c66affSColin Finck bufsize--;
2334c2c66affSColin Finck
2335c2c66affSColin Finck ei = (E->p[nblimbs] >> bufsize) & 1;
2336c2c66affSColin Finck
2337c2c66affSColin Finck /*
2338c2c66affSColin Finck * skip leading 0s
2339c2c66affSColin Finck */
2340c2c66affSColin Finck if( ei == 0 && state == 0 )
2341c2c66affSColin Finck continue;
2342c2c66affSColin Finck
2343c2c66affSColin Finck if( ei == 0 && state == 1 )
2344c2c66affSColin Finck {
2345c2c66affSColin Finck /*
2346c2c66affSColin Finck * out of window, square X
2347c2c66affSColin Finck */
2348292f67afSThomas Faber mpi_montmul( X, X, N, mm, &T );
2349c2c66affSColin Finck continue;
2350c2c66affSColin Finck }
2351c2c66affSColin Finck
2352c2c66affSColin Finck /*
2353c2c66affSColin Finck * add ei to current window
2354c2c66affSColin Finck */
2355c2c66affSColin Finck state = 2;
2356c2c66affSColin Finck
2357c2c66affSColin Finck nbits++;
2358c2c66affSColin Finck wbits |= ( ei << ( wsize - nbits ) );
2359c2c66affSColin Finck
2360c2c66affSColin Finck if( nbits == wsize )
2361c2c66affSColin Finck {
2362c2c66affSColin Finck /*
2363c2c66affSColin Finck * X = X^wsize R^-1 mod N
2364c2c66affSColin Finck */
2365c2c66affSColin Finck for( i = 0; i < wsize; i++ )
2366292f67afSThomas Faber mpi_montmul( X, X, N, mm, &T );
2367c2c66affSColin Finck
2368c2c66affSColin Finck /*
2369c2c66affSColin Finck * X = X * W[wbits] R^-1 mod N
2370c2c66affSColin Finck */
2371*103a79ceSThomas Faber MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
2372*103a79ceSThomas Faber mpi_montmul( X, &WW, N, mm, &T );
2373c2c66affSColin Finck
2374c2c66affSColin Finck state--;
2375c2c66affSColin Finck nbits = 0;
2376c2c66affSColin Finck wbits = 0;
2377c2c66affSColin Finck }
2378c2c66affSColin Finck }
2379c2c66affSColin Finck
2380c2c66affSColin Finck /*
2381c2c66affSColin Finck * process the remaining bits
2382c2c66affSColin Finck */
2383c2c66affSColin Finck for( i = 0; i < nbits; i++ )
2384c2c66affSColin Finck {
2385292f67afSThomas Faber mpi_montmul( X, X, N, mm, &T );
2386c2c66affSColin Finck
2387c2c66affSColin Finck wbits <<= 1;
2388c2c66affSColin Finck
2389c2c66affSColin Finck if( ( wbits & ( one << wsize ) ) != 0 )
2390292f67afSThomas Faber mpi_montmul( X, &W[1], N, mm, &T );
2391c2c66affSColin Finck }
2392c2c66affSColin Finck
2393c2c66affSColin Finck /*
2394c2c66affSColin Finck * X = A^E * R * R^-1 mod N = A^E mod N
2395c2c66affSColin Finck */
2396292f67afSThomas Faber mpi_montred( X, N, mm, &T );
2397c2c66affSColin Finck
2398c2c66affSColin Finck if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
2399c2c66affSColin Finck {
2400c2c66affSColin Finck X->s = -1;
2401c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
2402c2c66affSColin Finck }
2403c2c66affSColin Finck
2404c2c66affSColin Finck cleanup:
2405c2c66affSColin Finck
2406c2c66affSColin Finck for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
2407c2c66affSColin Finck mbedtls_mpi_free( &W[i] );
2408c2c66affSColin Finck
2409c2c66affSColin Finck mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
2410*103a79ceSThomas Faber mbedtls_mpi_free( &WW );
2411c2c66affSColin Finck
2412c2c66affSColin Finck if( _RR == NULL || _RR->p == NULL )
2413c2c66affSColin Finck mbedtls_mpi_free( &RR );
2414c2c66affSColin Finck
2415c2c66affSColin Finck return( ret );
2416c2c66affSColin Finck }
2417c2c66affSColin Finck
2418c2c66affSColin Finck /*
2419c2c66affSColin Finck * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2420c2c66affSColin Finck */
mbedtls_mpi_gcd(mbedtls_mpi * G,const mbedtls_mpi * A,const mbedtls_mpi * B)2421c2c66affSColin Finck int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
2422c2c66affSColin Finck {
2423c2c66affSColin Finck int ret;
2424c2c66affSColin Finck size_t lz, lzt;
2425c2c66affSColin Finck mbedtls_mpi TG, TA, TB;
2426c2c66affSColin Finck
2427cbda039fSThomas Faber MPI_VALIDATE_RET( G != NULL );
2428cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL );
2429cbda039fSThomas Faber MPI_VALIDATE_RET( B != NULL );
2430cbda039fSThomas Faber
2431c2c66affSColin Finck mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
2432c2c66affSColin Finck
2433c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2434c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
2435c2c66affSColin Finck
2436c2c66affSColin Finck lz = mbedtls_mpi_lsb( &TA );
2437c2c66affSColin Finck lzt = mbedtls_mpi_lsb( &TB );
2438c2c66affSColin Finck
2439*103a79ceSThomas Faber /* The loop below gives the correct result when A==0 but not when B==0.
2440*103a79ceSThomas Faber * So have a special case for B==0. Leverage the fact that we just
2441*103a79ceSThomas Faber * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2442*103a79ceSThomas Faber * slightly more efficient than cmp_int(). */
2443*103a79ceSThomas Faber if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 )
2444*103a79ceSThomas Faber {
2445*103a79ceSThomas Faber ret = mbedtls_mpi_copy( G, A );
2446*103a79ceSThomas Faber goto cleanup;
2447*103a79ceSThomas Faber }
2448*103a79ceSThomas Faber
2449c2c66affSColin Finck if( lzt < lz )
2450c2c66affSColin Finck lz = lzt;
2451c2c66affSColin Finck
2452c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2453c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
2454c2c66affSColin Finck
2455c2c66affSColin Finck TA.s = TB.s = 1;
2456c2c66affSColin Finck
2457*103a79ceSThomas Faber /* We mostly follow the procedure described in HAC 14.54, but with some
2458*103a79ceSThomas Faber * minor differences:
2459*103a79ceSThomas Faber * - Sequences of multiplications or divisions by 2 are grouped into a
2460*103a79ceSThomas Faber * single shift operation.
2461*103a79ceSThomas Faber * - The procedure in HAC assumes that 0 < TB <= TA.
2462*103a79ceSThomas Faber * - The condition TB <= TA is not actually necessary for correctness.
2463*103a79ceSThomas Faber * TA and TB have symmetric roles except for the loop termination
2464*103a79ceSThomas Faber * condition, and the shifts at the beginning of the loop body
2465*103a79ceSThomas Faber * remove any significance from the ordering of TA vs TB before
2466*103a79ceSThomas Faber * the shifts.
2467*103a79ceSThomas Faber * - If TA = 0, the loop goes through 0 iterations and the result is
2468*103a79ceSThomas Faber * correctly TB.
2469*103a79ceSThomas Faber * - The case TB = 0 was short-circuited above.
2470*103a79ceSThomas Faber *
2471*103a79ceSThomas Faber * For the correctness proof below, decompose the original values of
2472*103a79ceSThomas Faber * A and B as
2473*103a79ceSThomas Faber * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2474*103a79ceSThomas Faber * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2475*103a79ceSThomas Faber * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2476*103a79ceSThomas Faber * and gcd(A',B') is odd or 0.
2477*103a79ceSThomas Faber *
2478*103a79ceSThomas Faber * At the beginning, we have TA = |A|/2^a and TB = |B|/2^b.
2479*103a79ceSThomas Faber * The code maintains the following invariant:
2480*103a79ceSThomas Faber * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
2481*103a79ceSThomas Faber */
2482*103a79ceSThomas Faber
2483*103a79ceSThomas Faber /* Proof that the loop terminates:
2484*103a79ceSThomas Faber * At each iteration, either the right-shift by 1 is made on a nonzero
2485*103a79ceSThomas Faber * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2486*103a79ceSThomas Faber * by at least 1, or the right-shift by 1 is made on zero and then
2487*103a79ceSThomas Faber * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2488*103a79ceSThomas Faber * since in that case TB is calculated from TB-TA with the condition TB>TA).
2489*103a79ceSThomas Faber */
2490c2c66affSColin Finck while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
2491c2c66affSColin Finck {
2492*103a79ceSThomas Faber /* Divisions by 2 preserve the invariant (I). */
2493c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2494c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
2495c2c66affSColin Finck
2496*103a79ceSThomas Faber /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2497*103a79ceSThomas Faber * TA-TB is even so the division by 2 has an integer result.
2498*103a79ceSThomas Faber * Invariant (I) is preserved since any odd divisor of both TA and TB
2499*103a79ceSThomas Faber * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
2500*103a79ceSThomas Faber * also divides TB, and any odd divisior of both TB and |TA-TB|/2 also
2501*103a79ceSThomas Faber * divides TA.
2502*103a79ceSThomas Faber */
2503c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
2504c2c66affSColin Finck {
2505c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2506c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
2507c2c66affSColin Finck }
2508c2c66affSColin Finck else
2509c2c66affSColin Finck {
2510c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2511c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
2512c2c66affSColin Finck }
2513*103a79ceSThomas Faber /* Note that one of TA or TB is still odd. */
2514c2c66affSColin Finck }
2515c2c66affSColin Finck
2516*103a79ceSThomas Faber /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2517*103a79ceSThomas Faber * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2518*103a79ceSThomas Faber * - If there was at least one loop iteration, then one of TA or TB is odd,
2519*103a79ceSThomas Faber * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2520*103a79ceSThomas Faber * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2521*103a79ceSThomas Faber * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
2522*103a79ceSThomas Faber * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
2523*103a79ceSThomas Faber */
2524*103a79ceSThomas Faber
2525c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2526c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
2527c2c66affSColin Finck
2528c2c66affSColin Finck cleanup:
2529c2c66affSColin Finck
2530c2c66affSColin Finck mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
2531c2c66affSColin Finck
2532c2c66affSColin Finck return( ret );
2533c2c66affSColin Finck }
2534c2c66affSColin Finck
2535c2c66affSColin Finck /*
2536c2c66affSColin Finck * Fill X with size bytes of random.
2537c2c66affSColin Finck *
2538c2c66affSColin Finck * Use a temporary bytes representation to make sure the result is the same
2539c2c66affSColin Finck * regardless of the platform endianness (useful when f_rng is actually
2540c2c66affSColin Finck * deterministic, eg for tests).
2541c2c66affSColin Finck */
mbedtls_mpi_fill_random(mbedtls_mpi * X,size_t size,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)2542c2c66affSColin Finck int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
2543c2c66affSColin Finck int (*f_rng)(void *, unsigned char *, size_t),
2544c2c66affSColin Finck void *p_rng )
2545c2c66affSColin Finck {
2546c2c66affSColin Finck int ret;
2547cbda039fSThomas Faber size_t const limbs = CHARS_TO_LIMBS( size );
2548cbda039fSThomas Faber size_t const overhead = ( limbs * ciL ) - size;
2549cbda039fSThomas Faber unsigned char *Xp;
2550c2c66affSColin Finck
2551cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
2552cbda039fSThomas Faber MPI_VALIDATE_RET( f_rng != NULL );
2553c2c66affSColin Finck
2554cbda039fSThomas Faber /* Ensure that target MPI has exactly the necessary number of limbs */
2555cbda039fSThomas Faber if( X->n != limbs )
2556cbda039fSThomas Faber {
2557cbda039fSThomas Faber mbedtls_mpi_free( X );
2558cbda039fSThomas Faber mbedtls_mpi_init( X );
2559cbda039fSThomas Faber MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2560cbda039fSThomas Faber }
2561cbda039fSThomas Faber MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
2562cbda039fSThomas Faber
2563cbda039fSThomas Faber Xp = (unsigned char*) X->p;
2564cbda039fSThomas Faber MBEDTLS_MPI_CHK( f_rng( p_rng, Xp + overhead, size ) );
2565cbda039fSThomas Faber
2566cbda039fSThomas Faber mpi_bigendian_to_host( X->p, limbs );
2567c2c66affSColin Finck
2568c2c66affSColin Finck cleanup:
2569c2c66affSColin Finck return( ret );
2570c2c66affSColin Finck }
2571c2c66affSColin Finck
2572c2c66affSColin Finck /*
2573c2c66affSColin Finck * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2574c2c66affSColin Finck */
mbedtls_mpi_inv_mod(mbedtls_mpi * X,const mbedtls_mpi * A,const mbedtls_mpi * N)2575c2c66affSColin Finck int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
2576c2c66affSColin Finck {
2577c2c66affSColin Finck int ret;
2578c2c66affSColin Finck mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
2579cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
2580cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL );
2581cbda039fSThomas Faber MPI_VALIDATE_RET( N != NULL );
2582c2c66affSColin Finck
2583c2c66affSColin Finck if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
2584c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2585c2c66affSColin Finck
2586c2c66affSColin Finck mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2587c2c66affSColin Finck mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2588c2c66affSColin Finck mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
2589c2c66affSColin Finck
2590c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
2591c2c66affSColin Finck
2592c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
2593c2c66affSColin Finck {
2594c2c66affSColin Finck ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2595c2c66affSColin Finck goto cleanup;
2596c2c66affSColin Finck }
2597c2c66affSColin Finck
2598c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2599c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2600c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2601c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
2602c2c66affSColin Finck
2603c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2604c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2605c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2606c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
2607c2c66affSColin Finck
2608c2c66affSColin Finck do
2609c2c66affSColin Finck {
2610c2c66affSColin Finck while( ( TU.p[0] & 1 ) == 0 )
2611c2c66affSColin Finck {
2612c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
2613c2c66affSColin Finck
2614c2c66affSColin Finck if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2615c2c66affSColin Finck {
2616c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2617c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
2618c2c66affSColin Finck }
2619c2c66affSColin Finck
2620c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2621c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
2622c2c66affSColin Finck }
2623c2c66affSColin Finck
2624c2c66affSColin Finck while( ( TV.p[0] & 1 ) == 0 )
2625c2c66affSColin Finck {
2626c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
2627c2c66affSColin Finck
2628c2c66affSColin Finck if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2629c2c66affSColin Finck {
2630c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2631c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
2632c2c66affSColin Finck }
2633c2c66affSColin Finck
2634c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2635c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
2636c2c66affSColin Finck }
2637c2c66affSColin Finck
2638c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
2639c2c66affSColin Finck {
2640c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2641c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2642c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
2643c2c66affSColin Finck }
2644c2c66affSColin Finck else
2645c2c66affSColin Finck {
2646c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2647c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2648c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
2649c2c66affSColin Finck }
2650c2c66affSColin Finck }
2651c2c66affSColin Finck while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
2652c2c66affSColin Finck
2653c2c66affSColin Finck while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2654c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
2655c2c66affSColin Finck
2656c2c66affSColin Finck while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2657c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
2658c2c66affSColin Finck
2659c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
2660c2c66affSColin Finck
2661c2c66affSColin Finck cleanup:
2662c2c66affSColin Finck
2663c2c66affSColin Finck mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2664c2c66affSColin Finck mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2665c2c66affSColin Finck mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
2666c2c66affSColin Finck
2667c2c66affSColin Finck return( ret );
2668c2c66affSColin Finck }
2669c2c66affSColin Finck
2670c2c66affSColin Finck #if defined(MBEDTLS_GENPRIME)
2671c2c66affSColin Finck
2672c2c66affSColin Finck static const int small_prime[] =
2673c2c66affSColin Finck {
2674c2c66affSColin Finck 3, 5, 7, 11, 13, 17, 19, 23,
2675c2c66affSColin Finck 29, 31, 37, 41, 43, 47, 53, 59,
2676c2c66affSColin Finck 61, 67, 71, 73, 79, 83, 89, 97,
2677c2c66affSColin Finck 101, 103, 107, 109, 113, 127, 131, 137,
2678c2c66affSColin Finck 139, 149, 151, 157, 163, 167, 173, 179,
2679c2c66affSColin Finck 181, 191, 193, 197, 199, 211, 223, 227,
2680c2c66affSColin Finck 229, 233, 239, 241, 251, 257, 263, 269,
2681c2c66affSColin Finck 271, 277, 281, 283, 293, 307, 311, 313,
2682c2c66affSColin Finck 317, 331, 337, 347, 349, 353, 359, 367,
2683c2c66affSColin Finck 373, 379, 383, 389, 397, 401, 409, 419,
2684c2c66affSColin Finck 421, 431, 433, 439, 443, 449, 457, 461,
2685c2c66affSColin Finck 463, 467, 479, 487, 491, 499, 503, 509,
2686c2c66affSColin Finck 521, 523, 541, 547, 557, 563, 569, 571,
2687c2c66affSColin Finck 577, 587, 593, 599, 601, 607, 613, 617,
2688c2c66affSColin Finck 619, 631, 641, 643, 647, 653, 659, 661,
2689c2c66affSColin Finck 673, 677, 683, 691, 701, 709, 719, 727,
2690c2c66affSColin Finck 733, 739, 743, 751, 757, 761, 769, 773,
2691c2c66affSColin Finck 787, 797, 809, 811, 821, 823, 827, 829,
2692c2c66affSColin Finck 839, 853, 857, 859, 863, 877, 881, 883,
2693c2c66affSColin Finck 887, 907, 911, 919, 929, 937, 941, 947,
2694c2c66affSColin Finck 953, 967, 971, 977, 983, 991, 997, -103
2695c2c66affSColin Finck };
2696c2c66affSColin Finck
2697c2c66affSColin Finck /*
2698c2c66affSColin Finck * Small divisors test (X must be positive)
2699c2c66affSColin Finck *
2700c2c66affSColin Finck * Return values:
2701c2c66affSColin Finck * 0: no small factor (possible prime, more tests needed)
2702c2c66affSColin Finck * 1: certain prime
2703c2c66affSColin Finck * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2704c2c66affSColin Finck * other negative: error
2705c2c66affSColin Finck */
mpi_check_small_factors(const mbedtls_mpi * X)2706c2c66affSColin Finck static int mpi_check_small_factors( const mbedtls_mpi *X )
2707c2c66affSColin Finck {
2708c2c66affSColin Finck int ret = 0;
2709c2c66affSColin Finck size_t i;
2710c2c66affSColin Finck mbedtls_mpi_uint r;
2711c2c66affSColin Finck
2712c2c66affSColin Finck if( ( X->p[0] & 1 ) == 0 )
2713c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
2714c2c66affSColin Finck
2715c2c66affSColin Finck for( i = 0; small_prime[i] > 0; i++ )
2716c2c66affSColin Finck {
2717c2c66affSColin Finck if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
2718c2c66affSColin Finck return( 1 );
2719c2c66affSColin Finck
2720c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
2721c2c66affSColin Finck
2722c2c66affSColin Finck if( r == 0 )
2723c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
2724c2c66affSColin Finck }
2725c2c66affSColin Finck
2726c2c66affSColin Finck cleanup:
2727c2c66affSColin Finck return( ret );
2728c2c66affSColin Finck }
2729c2c66affSColin Finck
2730c2c66affSColin Finck /*
2731c2c66affSColin Finck * Miller-Rabin pseudo-primality test (HAC 4.24)
2732c2c66affSColin Finck */
mpi_miller_rabin(const mbedtls_mpi * X,size_t rounds,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)27330ba5bc40SThomas Faber static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
2734c2c66affSColin Finck int (*f_rng)(void *, unsigned char *, size_t),
2735c2c66affSColin Finck void *p_rng )
2736c2c66affSColin Finck {
2737c2c66affSColin Finck int ret, count;
27380ba5bc40SThomas Faber size_t i, j, k, s;
2739c2c66affSColin Finck mbedtls_mpi W, R, T, A, RR;
2740c2c66affSColin Finck
2741cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
2742cbda039fSThomas Faber MPI_VALIDATE_RET( f_rng != NULL );
2743cbda039fSThomas Faber
2744cbda039fSThomas Faber mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2745cbda039fSThomas Faber mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2746c2c66affSColin Finck mbedtls_mpi_init( &RR );
2747c2c66affSColin Finck
2748c2c66affSColin Finck /*
2749c2c66affSColin Finck * W = |X| - 1
2750c2c66affSColin Finck * R = W >> lsb( W )
2751c2c66affSColin Finck */
2752c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2753c2c66affSColin Finck s = mbedtls_mpi_lsb( &W );
2754c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2755c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
2756c2c66affSColin Finck
27570ba5bc40SThomas Faber for( i = 0; i < rounds; i++ )
2758c2c66affSColin Finck {
2759c2c66affSColin Finck /*
2760c2c66affSColin Finck * pick a random A, 1 < A < |X| - 1
2761c2c66affSColin Finck */
2762c2c66affSColin Finck count = 0;
2763c2c66affSColin Finck do {
2764c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
2765c2c66affSColin Finck
2766c2c66affSColin Finck j = mbedtls_mpi_bitlen( &A );
2767c2c66affSColin Finck k = mbedtls_mpi_bitlen( &W );
2768c2c66affSColin Finck if (j > k) {
27690ba5bc40SThomas Faber A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
2770c2c66affSColin Finck }
2771c2c66affSColin Finck
2772c2c66affSColin Finck if (count++ > 30) {
2773c1eccaffSThomas Faber ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2774c1eccaffSThomas Faber goto cleanup;
2775c2c66affSColin Finck }
2776c2c66affSColin Finck
2777c2c66affSColin Finck } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2778c2c66affSColin Finck mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
2779c2c66affSColin Finck
2780c2c66affSColin Finck /*
2781c2c66affSColin Finck * A = A^R mod |X|
2782c2c66affSColin Finck */
2783c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
2784c2c66affSColin Finck
2785c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2786c2c66affSColin Finck mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
2787c2c66affSColin Finck continue;
2788c2c66affSColin Finck
2789c2c66affSColin Finck j = 1;
2790c2c66affSColin Finck while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
2791c2c66affSColin Finck {
2792c2c66affSColin Finck /*
2793c2c66affSColin Finck * A = A * A mod |X|
2794c2c66affSColin Finck */
2795c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2796c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
2797c2c66affSColin Finck
2798c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
2799c2c66affSColin Finck break;
2800c2c66affSColin Finck
2801c2c66affSColin Finck j++;
2802c2c66affSColin Finck }
2803c2c66affSColin Finck
2804c2c66affSColin Finck /*
2805c2c66affSColin Finck * not prime if A != |X| - 1 or A == 1
2806c2c66affSColin Finck */
2807c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2808c2c66affSColin Finck mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
2809c2c66affSColin Finck {
2810c2c66affSColin Finck ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2811c2c66affSColin Finck break;
2812c2c66affSColin Finck }
2813c2c66affSColin Finck }
2814c2c66affSColin Finck
2815c2c66affSColin Finck cleanup:
2816cbda039fSThomas Faber mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2817cbda039fSThomas Faber mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2818c2c66affSColin Finck mbedtls_mpi_free( &RR );
2819c2c66affSColin Finck
2820c2c66affSColin Finck return( ret );
2821c2c66affSColin Finck }
2822c2c66affSColin Finck
2823c2c66affSColin Finck /*
2824c2c66affSColin Finck * Pseudo-primality test: small factors, then Miller-Rabin
2825c2c66affSColin Finck */
mbedtls_mpi_is_prime_ext(const mbedtls_mpi * X,int rounds,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)2826cbda039fSThomas Faber int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2827c2c66affSColin Finck int (*f_rng)(void *, unsigned char *, size_t),
2828c2c66affSColin Finck void *p_rng )
2829c2c66affSColin Finck {
2830c2c66affSColin Finck int ret;
2831c2c66affSColin Finck mbedtls_mpi XX;
2832cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
2833cbda039fSThomas Faber MPI_VALIDATE_RET( f_rng != NULL );
2834c2c66affSColin Finck
2835c2c66affSColin Finck XX.s = 1;
2836c2c66affSColin Finck XX.n = X->n;
2837c2c66affSColin Finck XX.p = X->p;
2838c2c66affSColin Finck
2839c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2840c2c66affSColin Finck mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2841c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
2842c2c66affSColin Finck
2843c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
2844c2c66affSColin Finck return( 0 );
2845c2c66affSColin Finck
2846c2c66affSColin Finck if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2847c2c66affSColin Finck {
2848c2c66affSColin Finck if( ret == 1 )
2849c2c66affSColin Finck return( 0 );
2850c2c66affSColin Finck
2851c2c66affSColin Finck return( ret );
2852c2c66affSColin Finck }
2853c2c66affSColin Finck
28540ba5bc40SThomas Faber return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
28550ba5bc40SThomas Faber }
28560ba5bc40SThomas Faber
2857cbda039fSThomas Faber #if !defined(MBEDTLS_DEPRECATED_REMOVED)
28580ba5bc40SThomas Faber /*
28590ba5bc40SThomas Faber * Pseudo-primality test, error probability 2^-80
28600ba5bc40SThomas Faber */
mbedtls_mpi_is_prime(const mbedtls_mpi * X,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)28610ba5bc40SThomas Faber int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
28620ba5bc40SThomas Faber int (*f_rng)(void *, unsigned char *, size_t),
28630ba5bc40SThomas Faber void *p_rng )
28640ba5bc40SThomas Faber {
2865cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
2866cbda039fSThomas Faber MPI_VALIDATE_RET( f_rng != NULL );
2867cbda039fSThomas Faber
2868cbda039fSThomas Faber /*
2869cbda039fSThomas Faber * In the past our key generation aimed for an error rate of at most
2870cbda039fSThomas Faber * 2^-80. Since this function is deprecated, aim for the same certainty
2871cbda039fSThomas Faber * here as well.
2872cbda039fSThomas Faber */
2873cbda039fSThomas Faber return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
2874c2c66affSColin Finck }
2875cbda039fSThomas Faber #endif
2876c2c66affSColin Finck
2877c2c66affSColin Finck /*
2878c2c66affSColin Finck * Prime number generation
2879cbda039fSThomas Faber *
2880cbda039fSThomas Faber * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2881cbda039fSThomas Faber * be either 1024 bits or 1536 bits long, and flags must contain
2882cbda039fSThomas Faber * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
2883c2c66affSColin Finck */
mbedtls_mpi_gen_prime(mbedtls_mpi * X,size_t nbits,int flags,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)2884cbda039fSThomas Faber int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
2885c2c66affSColin Finck int (*f_rng)(void *, unsigned char *, size_t),
2886c2c66affSColin Finck void *p_rng )
2887c2c66affSColin Finck {
2888cbda039fSThomas Faber #ifdef MBEDTLS_HAVE_INT64
2889cbda039fSThomas Faber // ceil(2^63.5)
2890cbda039fSThomas Faber #define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2891cbda039fSThomas Faber #else
2892cbda039fSThomas Faber // ceil(2^31.5)
2893cbda039fSThomas Faber #define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2894cbda039fSThomas Faber #endif
2895cbda039fSThomas Faber int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2896c2c66affSColin Finck size_t k, n;
28970ba5bc40SThomas Faber int rounds;
2898c2c66affSColin Finck mbedtls_mpi_uint r;
2899c2c66affSColin Finck mbedtls_mpi Y;
2900c2c66affSColin Finck
2901cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL );
2902cbda039fSThomas Faber MPI_VALIDATE_RET( f_rng != NULL );
2903cbda039fSThomas Faber
2904c2c66affSColin Finck if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2905c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2906c2c66affSColin Finck
2907c2c66affSColin Finck mbedtls_mpi_init( &Y );
2908c2c66affSColin Finck
2909c2c66affSColin Finck n = BITS_TO_LIMBS( nbits );
2910c2c66affSColin Finck
2911cbda039fSThomas Faber if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2912cbda039fSThomas Faber {
29130ba5bc40SThomas Faber /*
29140ba5bc40SThomas Faber * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
29150ba5bc40SThomas Faber */
29160ba5bc40SThomas Faber rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
29170ba5bc40SThomas Faber ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
29180ba5bc40SThomas Faber ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2919cbda039fSThomas Faber }
2920cbda039fSThomas Faber else
2921cbda039fSThomas Faber {
2922cbda039fSThomas Faber /*
2923cbda039fSThomas Faber * 2^-100 error probability, number of rounds computed based on HAC,
2924cbda039fSThomas Faber * fact 4.48
2925cbda039fSThomas Faber */
2926cbda039fSThomas Faber rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2927cbda039fSThomas Faber ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2928cbda039fSThomas Faber ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2929cbda039fSThomas Faber ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2930cbda039fSThomas Faber }
29310ba5bc40SThomas Faber
2932cbda039fSThomas Faber while( 1 )
2933cbda039fSThomas Faber {
2934c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2935cbda039fSThomas Faber /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2936cbda039fSThomas Faber if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2937c2c66affSColin Finck
2938cbda039fSThomas Faber k = n * biL;
2939cbda039fSThomas Faber if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2940c2c66affSColin Finck X->p[0] |= 1;
2941c2c66affSColin Finck
2942cbda039fSThomas Faber if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
2943c2c66affSColin Finck {
2944cbda039fSThomas Faber ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
2945cbda039fSThomas Faber
2946c2c66affSColin Finck if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2947c2c66affSColin Finck goto cleanup;
2948c2c66affSColin Finck }
2949c2c66affSColin Finck else
2950c2c66affSColin Finck {
2951c2c66affSColin Finck /*
2952c2c66affSColin Finck * An necessary condition for Y and X = 2Y + 1 to be prime
2953c2c66affSColin Finck * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2954c2c66affSColin Finck * Make sure it is satisfied, while keeping X = 3 mod 4
2955c2c66affSColin Finck */
2956c2c66affSColin Finck
2957c2c66affSColin Finck X->p[0] |= 2;
2958c2c66affSColin Finck
2959c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2960c2c66affSColin Finck if( r == 0 )
2961c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2962c2c66affSColin Finck else if( r == 1 )
2963c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2964c2c66affSColin Finck
2965c2c66affSColin Finck /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2966c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2967c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2968c2c66affSColin Finck
2969c2c66affSColin Finck while( 1 )
2970c2c66affSColin Finck {
2971c2c66affSColin Finck /*
2972c2c66affSColin Finck * First, check small factors for X and Y
2973c2c66affSColin Finck * before doing Miller-Rabin on any of them
2974c2c66affSColin Finck */
2975c2c66affSColin Finck if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2976c2c66affSColin Finck ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
29770ba5bc40SThomas Faber ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
29780ba5bc40SThomas Faber == 0 &&
29790ba5bc40SThomas Faber ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
29800ba5bc40SThomas Faber == 0 )
2981cbda039fSThomas Faber goto cleanup;
2982c2c66affSColin Finck
2983c2c66affSColin Finck if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2984c2c66affSColin Finck goto cleanup;
2985c2c66affSColin Finck
2986c2c66affSColin Finck /*
2987c2c66affSColin Finck * Next candidates. We want to preserve Y = (X-1) / 2 and
2988c2c66affSColin Finck * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2989c2c66affSColin Finck * so up Y by 6 and X by 12.
2990c2c66affSColin Finck */
2991c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2992c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
2993c2c66affSColin Finck }
2994c2c66affSColin Finck }
2995cbda039fSThomas Faber }
2996c2c66affSColin Finck
2997c2c66affSColin Finck cleanup:
2998c2c66affSColin Finck
2999c2c66affSColin Finck mbedtls_mpi_free( &Y );
3000c2c66affSColin Finck
3001c2c66affSColin Finck return( ret );
3002c2c66affSColin Finck }
3003c2c66affSColin Finck
3004c2c66affSColin Finck #endif /* MBEDTLS_GENPRIME */
3005c2c66affSColin Finck
3006c2c66affSColin Finck #if defined(MBEDTLS_SELF_TEST)
3007c2c66affSColin Finck
3008c2c66affSColin Finck #define GCD_PAIR_COUNT 3
3009c2c66affSColin Finck
3010c2c66affSColin Finck static const int gcd_pairs[GCD_PAIR_COUNT][3] =
3011c2c66affSColin Finck {
3012c2c66affSColin Finck { 693, 609, 21 },
3013c2c66affSColin Finck { 1764, 868, 28 },
3014c2c66affSColin Finck { 768454923, 542167814, 1 }
3015c2c66affSColin Finck };
3016c2c66affSColin Finck
3017c2c66affSColin Finck /*
3018c2c66affSColin Finck * Checkup routine
3019c2c66affSColin Finck */
mbedtls_mpi_self_test(int verbose)3020c2c66affSColin Finck int mbedtls_mpi_self_test( int verbose )
3021c2c66affSColin Finck {
3022c2c66affSColin Finck int ret, i;
3023c2c66affSColin Finck mbedtls_mpi A, E, N, X, Y, U, V;
3024c2c66affSColin Finck
3025c2c66affSColin Finck mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
3026c2c66affSColin Finck mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
3027c2c66affSColin Finck
3028c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
3029c2c66affSColin Finck "EFE021C2645FD1DC586E69184AF4A31E" \
3030c2c66affSColin Finck "D5F53E93B5F123FA41680867BA110131" \
3031c2c66affSColin Finck "944FE7952E2517337780CB0DB80E61AA" \
3032c2c66affSColin Finck "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
3033c2c66affSColin Finck
3034c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
3035c2c66affSColin Finck "B2E7EFD37075B9F03FF989C7C5051C20" \
3036c2c66affSColin Finck "34D2A323810251127E7BF8625A4F49A5" \
3037c2c66affSColin Finck "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
3038c2c66affSColin Finck "5B5C25763222FEFCCFC38B832366C29E" ) );
3039c2c66affSColin Finck
3040c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
3041c2c66affSColin Finck "0066A198186C18C10B2F5ED9B522752A" \
3042c2c66affSColin Finck "9830B69916E535C8F047518A889A43A5" \
3043c2c66affSColin Finck "94B6BED27A168D31D4A52F88925AA8F5" ) );
3044c2c66affSColin Finck
3045c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
3046c2c66affSColin Finck
3047c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
3048c2c66affSColin Finck "602AB7ECA597A3D6B56FF9829A5E8B85" \
3049c2c66affSColin Finck "9E857EA95A03512E2BAE7391688D264A" \
3050c2c66affSColin Finck "A5663B0341DB9CCFD2C4C5F421FEC814" \
3051c2c66affSColin Finck "8001B72E848A38CAE1C65F78E56ABDEF" \
3052c2c66affSColin Finck "E12D3C039B8A02D6BE593F0BBBDA56F1" \
3053c2c66affSColin Finck "ECF677152EF804370C1A305CAF3B5BF1" \
3054c2c66affSColin Finck "30879B56C61DE584A0F53A2447A51E" ) );
3055c2c66affSColin Finck
3056c2c66affSColin Finck if( verbose != 0 )
3057c2c66affSColin Finck mbedtls_printf( " MPI test #1 (mul_mpi): " );
3058c2c66affSColin Finck
3059c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
3060c2c66affSColin Finck {
3061c2c66affSColin Finck if( verbose != 0 )
3062c2c66affSColin Finck mbedtls_printf( "failed\n" );
3063c2c66affSColin Finck
3064c2c66affSColin Finck ret = 1;
3065c2c66affSColin Finck goto cleanup;
3066c2c66affSColin Finck }
3067c2c66affSColin Finck
3068c2c66affSColin Finck if( verbose != 0 )
3069c2c66affSColin Finck mbedtls_printf( "passed\n" );
3070c2c66affSColin Finck
3071c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
3072c2c66affSColin Finck
3073c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
3074c2c66affSColin Finck "256567336059E52CAE22925474705F39A94" ) );
3075c2c66affSColin Finck
3076c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
3077c2c66affSColin Finck "6613F26162223DF488E9CD48CC132C7A" \
3078c2c66affSColin Finck "0AC93C701B001B092E4E5B9F73BCD27B" \
3079c2c66affSColin Finck "9EE50D0657C77F374E903CDFA4C642" ) );
3080c2c66affSColin Finck
3081c2c66affSColin Finck if( verbose != 0 )
3082c2c66affSColin Finck mbedtls_printf( " MPI test #2 (div_mpi): " );
3083c2c66affSColin Finck
3084c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
3085c2c66affSColin Finck mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
3086c2c66affSColin Finck {
3087c2c66affSColin Finck if( verbose != 0 )
3088c2c66affSColin Finck mbedtls_printf( "failed\n" );
3089c2c66affSColin Finck
3090c2c66affSColin Finck ret = 1;
3091c2c66affSColin Finck goto cleanup;
3092c2c66affSColin Finck }
3093c2c66affSColin Finck
3094c2c66affSColin Finck if( verbose != 0 )
3095c2c66affSColin Finck mbedtls_printf( "passed\n" );
3096c2c66affSColin Finck
3097c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
3098c2c66affSColin Finck
3099c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
3100c2c66affSColin Finck "36E139AEA55215609D2816998ED020BB" \
3101c2c66affSColin Finck "BD96C37890F65171D948E9BC7CBAA4D9" \
3102c2c66affSColin Finck "325D24D6A3C12710F10A09FA08AB87" ) );
3103c2c66affSColin Finck
3104c2c66affSColin Finck if( verbose != 0 )
3105c2c66affSColin Finck mbedtls_printf( " MPI test #3 (exp_mod): " );
3106c2c66affSColin Finck
3107c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
3108c2c66affSColin Finck {
3109c2c66affSColin Finck if( verbose != 0 )
3110c2c66affSColin Finck mbedtls_printf( "failed\n" );
3111c2c66affSColin Finck
3112c2c66affSColin Finck ret = 1;
3113c2c66affSColin Finck goto cleanup;
3114c2c66affSColin Finck }
3115c2c66affSColin Finck
3116c2c66affSColin Finck if( verbose != 0 )
3117c2c66affSColin Finck mbedtls_printf( "passed\n" );
3118c2c66affSColin Finck
3119c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
3120c2c66affSColin Finck
3121c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
3122c2c66affSColin Finck "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3123c2c66affSColin Finck "C3DBA76456363A10869622EAC2DD84EC" \
3124c2c66affSColin Finck "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
3125c2c66affSColin Finck
3126c2c66affSColin Finck if( verbose != 0 )
3127c2c66affSColin Finck mbedtls_printf( " MPI test #4 (inv_mod): " );
3128c2c66affSColin Finck
3129c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
3130c2c66affSColin Finck {
3131c2c66affSColin Finck if( verbose != 0 )
3132c2c66affSColin Finck mbedtls_printf( "failed\n" );
3133c2c66affSColin Finck
3134c2c66affSColin Finck ret = 1;
3135c2c66affSColin Finck goto cleanup;
3136c2c66affSColin Finck }
3137c2c66affSColin Finck
3138c2c66affSColin Finck if( verbose != 0 )
3139c2c66affSColin Finck mbedtls_printf( "passed\n" );
3140c2c66affSColin Finck
3141c2c66affSColin Finck if( verbose != 0 )
3142c2c66affSColin Finck mbedtls_printf( " MPI test #5 (simple gcd): " );
3143c2c66affSColin Finck
3144c2c66affSColin Finck for( i = 0; i < GCD_PAIR_COUNT; i++ )
3145c2c66affSColin Finck {
3146c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
3147c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
3148c2c66affSColin Finck
3149c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
3150c2c66affSColin Finck
3151c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
3152c2c66affSColin Finck {
3153c2c66affSColin Finck if( verbose != 0 )
3154c2c66affSColin Finck mbedtls_printf( "failed at %d\n", i );
3155c2c66affSColin Finck
3156c2c66affSColin Finck ret = 1;
3157c2c66affSColin Finck goto cleanup;
3158c2c66affSColin Finck }
3159c2c66affSColin Finck }
3160c2c66affSColin Finck
3161c2c66affSColin Finck if( verbose != 0 )
3162c2c66affSColin Finck mbedtls_printf( "passed\n" );
3163c2c66affSColin Finck
3164c2c66affSColin Finck cleanup:
3165c2c66affSColin Finck
3166c2c66affSColin Finck if( ret != 0 && verbose != 0 )
3167c2c66affSColin Finck mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
3168c2c66affSColin Finck
3169c2c66affSColin Finck mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3170c2c66affSColin Finck mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
3171c2c66affSColin Finck
3172c2c66affSColin Finck if( verbose != 0 )
3173c2c66affSColin Finck mbedtls_printf( "\n" );
3174c2c66affSColin Finck
3175c2c66affSColin Finck return( ret );
3176c2c66affSColin Finck }
3177c2c66affSColin Finck
3178c2c66affSColin Finck #endif /* MBEDTLS_SELF_TEST */
3179c2c66affSColin Finck
3180c2c66affSColin Finck #endif /* MBEDTLS_BIGNUM_C */
3181