xref: /reactos/dll/3rdparty/mbedtls/bignum.c (revision cbda039f)
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"
73*cbda039fSThomas 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 
87*cbda039fSThomas Faber #define MPI_VALIDATE_RET( cond )                                       \
88*cbda039fSThomas Faber     MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
89*cbda039fSThomas Faber #define MPI_VALIDATE( cond )                                           \
90*cbda039fSThomas 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 
105*cbda039fSThomas Faber /* Implementation that should never be optimized out by the compiler */
106*cbda039fSThomas Faber static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
107*cbda039fSThomas Faber {
108*cbda039fSThomas Faber     mbedtls_platform_zeroize( v, ciL * n );
109*cbda039fSThomas Faber }
110*cbda039fSThomas Faber 
111c2c66affSColin Finck /*
112c2c66affSColin Finck  * Initialize one MPI
113c2c66affSColin Finck  */
114c2c66affSColin Finck void mbedtls_mpi_init( mbedtls_mpi *X )
115c2c66affSColin Finck {
116*cbda039fSThomas 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  */
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  */
145c2c66affSColin Finck int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
146c2c66affSColin Finck {
147c2c66affSColin Finck     mbedtls_mpi_uint *p;
148*cbda039fSThomas 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  */
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;
180*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
181*cbda039fSThomas Faber 
182*cbda039fSThomas Faber     if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
183*cbda039fSThomas 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  */
217c2c66affSColin Finck int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
218c2c66affSColin Finck {
219*cbda039fSThomas Faber     int ret = 0;
220c2c66affSColin Finck     size_t i;
221*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
222*cbda039fSThomas 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 
240*cbda039fSThomas Faber     if( X->n < i )
241*cbda039fSThomas Faber     {
242c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
243*cbda039fSThomas Faber     }
244*cbda039fSThomas Faber     else
245*cbda039fSThomas Faber     {
246*cbda039fSThomas Faber         memset( X->p + i, 0, ( X->n - i ) * ciL );
247*cbda039fSThomas 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  */
259c2c66affSColin Finck void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
260c2c66affSColin Finck {
261c2c66affSColin Finck     mbedtls_mpi T;
262*cbda039fSThomas Faber     MPI_VALIDATE( X != NULL );
263*cbda039fSThomas 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 
270c2c66affSColin Finck /*
271292f67afSThomas Faber  * Conditionally assign dest = src, without leaking information
272292f67afSThomas Faber  * about whether the assignment was made or not.
273292f67afSThomas Faber  * dest and src must be arrays of limbs of size n.
274292f67afSThomas Faber  * assign must be 0 or 1.
275292f67afSThomas Faber  */
276292f67afSThomas Faber static void mpi_safe_cond_assign( size_t n,
277292f67afSThomas Faber                                   mbedtls_mpi_uint *dest,
278292f67afSThomas Faber                                   const mbedtls_mpi_uint *src,
279292f67afSThomas Faber                                   unsigned char assign )
280292f67afSThomas Faber {
281292f67afSThomas Faber     size_t i;
282292f67afSThomas Faber     for( i = 0; i < n; i++ )
283292f67afSThomas Faber         dest[i] = dest[i] * ( 1 - assign ) + src[i] * assign;
284292f67afSThomas Faber }
285292f67afSThomas Faber 
286292f67afSThomas Faber /*
287c2c66affSColin Finck  * Conditionally assign X = Y, without leaking information
288c2c66affSColin Finck  * about whether the assignment was made or not.
289c2c66affSColin Finck  * (Leaking information about the respective sizes of X and Y is ok however.)
290c2c66affSColin Finck  */
291c2c66affSColin Finck int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
292c2c66affSColin Finck {
293c2c66affSColin Finck     int ret = 0;
294c2c66affSColin Finck     size_t i;
295*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
296*cbda039fSThomas Faber     MPI_VALIDATE_RET( Y != NULL );
297c2c66affSColin Finck 
298c2c66affSColin Finck     /* make sure assign is 0 or 1 in a time-constant manner */
299c2c66affSColin Finck     assign = (assign | (unsigned char)-assign) >> 7;
300c2c66affSColin Finck 
301c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
302c2c66affSColin Finck 
303c2c66affSColin Finck     X->s = X->s * ( 1 - assign ) + Y->s * assign;
304c2c66affSColin Finck 
305292f67afSThomas Faber     mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
306c2c66affSColin Finck 
307292f67afSThomas Faber     for( i = Y->n; i < X->n; i++ )
308c2c66affSColin Finck         X->p[i] *= ( 1 - assign );
309c2c66affSColin Finck 
310c2c66affSColin Finck cleanup:
311c2c66affSColin Finck     return( ret );
312c2c66affSColin Finck }
313c2c66affSColin Finck 
314c2c66affSColin Finck /*
315c2c66affSColin Finck  * Conditionally swap X and Y, without leaking information
316c2c66affSColin Finck  * about whether the swap was made or not.
317c2c66affSColin Finck  * Here it is not ok to simply swap the pointers, which whould lead to
318c2c66affSColin Finck  * different memory access patterns when X and Y are used afterwards.
319c2c66affSColin Finck  */
320c2c66affSColin Finck int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
321c2c66affSColin Finck {
322c2c66affSColin Finck     int ret, s;
323c2c66affSColin Finck     size_t i;
324c2c66affSColin Finck     mbedtls_mpi_uint tmp;
325*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
326*cbda039fSThomas Faber     MPI_VALIDATE_RET( Y != NULL );
327c2c66affSColin Finck 
328c2c66affSColin Finck     if( X == Y )
329c2c66affSColin Finck         return( 0 );
330c2c66affSColin Finck 
331c2c66affSColin Finck     /* make sure swap is 0 or 1 in a time-constant manner */
332c2c66affSColin Finck     swap = (swap | (unsigned char)-swap) >> 7;
333c2c66affSColin Finck 
334c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
335c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
336c2c66affSColin Finck 
337c2c66affSColin Finck     s = X->s;
338c2c66affSColin Finck     X->s = X->s * ( 1 - swap ) + Y->s * swap;
339c2c66affSColin Finck     Y->s = Y->s * ( 1 - swap ) +    s * swap;
340c2c66affSColin Finck 
341c2c66affSColin Finck 
342c2c66affSColin Finck     for( i = 0; i < X->n; i++ )
343c2c66affSColin Finck     {
344c2c66affSColin Finck         tmp = X->p[i];
345c2c66affSColin Finck         X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
346c2c66affSColin Finck         Y->p[i] = Y->p[i] * ( 1 - swap ) +     tmp * swap;
347c2c66affSColin Finck     }
348c2c66affSColin Finck 
349c2c66affSColin Finck cleanup:
350c2c66affSColin Finck     return( ret );
351c2c66affSColin Finck }
352c2c66affSColin Finck 
353c2c66affSColin Finck /*
354c2c66affSColin Finck  * Set value from integer
355c2c66affSColin Finck  */
356c2c66affSColin Finck int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
357c2c66affSColin Finck {
358c2c66affSColin Finck     int ret;
359*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
360c2c66affSColin Finck 
361c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
362c2c66affSColin Finck     memset( X->p, 0, X->n * ciL );
363c2c66affSColin Finck 
364c2c66affSColin Finck     X->p[0] = ( z < 0 ) ? -z : z;
365c2c66affSColin Finck     X->s    = ( z < 0 ) ? -1 : 1;
366c2c66affSColin Finck 
367c2c66affSColin Finck cleanup:
368c2c66affSColin Finck 
369c2c66affSColin Finck     return( ret );
370c2c66affSColin Finck }
371c2c66affSColin Finck 
372c2c66affSColin Finck /*
373c2c66affSColin Finck  * Get a specific bit
374c2c66affSColin Finck  */
375c2c66affSColin Finck int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
376c2c66affSColin Finck {
377*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
378*cbda039fSThomas Faber 
379c2c66affSColin Finck     if( X->n * biL <= pos )
380c2c66affSColin Finck         return( 0 );
381c2c66affSColin Finck 
382c2c66affSColin Finck     return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
383c2c66affSColin Finck }
384c2c66affSColin Finck 
3850ba5bc40SThomas Faber /* Get a specific byte, without range checks. */
3860ba5bc40SThomas Faber #define GET_BYTE( X, i )                                \
3870ba5bc40SThomas Faber     ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
3880ba5bc40SThomas Faber 
389c2c66affSColin Finck /*
390c2c66affSColin Finck  * Set a bit to a specific value of 0 or 1
391c2c66affSColin Finck  */
392c2c66affSColin Finck int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
393c2c66affSColin Finck {
394c2c66affSColin Finck     int ret = 0;
395c2c66affSColin Finck     size_t off = pos / biL;
396c2c66affSColin Finck     size_t idx = pos % biL;
397*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
398c2c66affSColin Finck 
399c2c66affSColin Finck     if( val != 0 && val != 1 )
400c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
401c2c66affSColin Finck 
402c2c66affSColin Finck     if( X->n * biL <= pos )
403c2c66affSColin Finck     {
404c2c66affSColin Finck         if( val == 0 )
405c2c66affSColin Finck             return( 0 );
406c2c66affSColin Finck 
407c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
408c2c66affSColin Finck     }
409c2c66affSColin Finck 
410c2c66affSColin Finck     X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
411c2c66affSColin Finck     X->p[off] |= (mbedtls_mpi_uint) val << idx;
412c2c66affSColin Finck 
413c2c66affSColin Finck cleanup:
414c2c66affSColin Finck 
415c2c66affSColin Finck     return( ret );
416c2c66affSColin Finck }
417c2c66affSColin Finck 
418c2c66affSColin Finck /*
419c2c66affSColin Finck  * Return the number of less significant zero-bits
420c2c66affSColin Finck  */
421c2c66affSColin Finck size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
422c2c66affSColin Finck {
423c2c66affSColin Finck     size_t i, j, count = 0;
424*cbda039fSThomas Faber     MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
425c2c66affSColin Finck 
426c2c66affSColin Finck     for( i = 0; i < X->n; i++ )
427c2c66affSColin Finck         for( j = 0; j < biL; j++, count++ )
428c2c66affSColin Finck             if( ( ( X->p[i] >> j ) & 1 ) != 0 )
429c2c66affSColin Finck                 return( count );
430c2c66affSColin Finck 
431c2c66affSColin Finck     return( 0 );
432c2c66affSColin Finck }
433c2c66affSColin Finck 
434c2c66affSColin Finck /*
435c2c66affSColin Finck  * Count leading zero bits in a given integer
436c2c66affSColin Finck  */
437c2c66affSColin Finck static size_t mbedtls_clz( const mbedtls_mpi_uint x )
438c2c66affSColin Finck {
439c2c66affSColin Finck     size_t j;
440c2c66affSColin Finck     mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
441c2c66affSColin Finck 
442c2c66affSColin Finck     for( j = 0; j < biL; j++ )
443c2c66affSColin Finck     {
444c2c66affSColin Finck         if( x & mask ) break;
445c2c66affSColin Finck 
446c2c66affSColin Finck         mask >>= 1;
447c2c66affSColin Finck     }
448c2c66affSColin Finck 
449c2c66affSColin Finck     return j;
450c2c66affSColin Finck }
451c2c66affSColin Finck 
452c2c66affSColin Finck /*
453c2c66affSColin Finck  * Return the number of bits
454c2c66affSColin Finck  */
455c2c66affSColin Finck size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
456c2c66affSColin Finck {
457c2c66affSColin Finck     size_t i, j;
458c2c66affSColin Finck 
459c2c66affSColin Finck     if( X->n == 0 )
460c2c66affSColin Finck         return( 0 );
461c2c66affSColin Finck 
462c2c66affSColin Finck     for( i = X->n - 1; i > 0; i-- )
463c2c66affSColin Finck         if( X->p[i] != 0 )
464c2c66affSColin Finck             break;
465c2c66affSColin Finck 
466c2c66affSColin Finck     j = biL - mbedtls_clz( X->p[i] );
467c2c66affSColin Finck 
468c2c66affSColin Finck     return( ( i * biL ) + j );
469c2c66affSColin Finck }
470c2c66affSColin Finck 
471c2c66affSColin Finck /*
472c2c66affSColin Finck  * Return the total size in bytes
473c2c66affSColin Finck  */
474c2c66affSColin Finck size_t mbedtls_mpi_size( const mbedtls_mpi *X )
475c2c66affSColin Finck {
476c2c66affSColin Finck     return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
477c2c66affSColin Finck }
478c2c66affSColin Finck 
479c2c66affSColin Finck /*
480c2c66affSColin Finck  * Convert an ASCII character to digit value
481c2c66affSColin Finck  */
482c2c66affSColin Finck static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
483c2c66affSColin Finck {
484c2c66affSColin Finck     *d = 255;
485c2c66affSColin Finck 
486c2c66affSColin Finck     if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
487c2c66affSColin Finck     if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
488c2c66affSColin Finck     if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
489c2c66affSColin Finck 
490c2c66affSColin Finck     if( *d >= (mbedtls_mpi_uint) radix )
491c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
492c2c66affSColin Finck 
493c2c66affSColin Finck     return( 0 );
494c2c66affSColin Finck }
495c2c66affSColin Finck 
496c2c66affSColin Finck /*
497c2c66affSColin Finck  * Import from an ASCII string
498c2c66affSColin Finck  */
499c2c66affSColin Finck int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
500c2c66affSColin Finck {
501c2c66affSColin Finck     int ret;
502c2c66affSColin Finck     size_t i, j, slen, n;
503c2c66affSColin Finck     mbedtls_mpi_uint d;
504c2c66affSColin Finck     mbedtls_mpi T;
505*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
506*cbda039fSThomas Faber     MPI_VALIDATE_RET( s != NULL );
507c2c66affSColin Finck 
508c2c66affSColin Finck     if( radix < 2 || radix > 16 )
509c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
510c2c66affSColin Finck 
511c2c66affSColin Finck     mbedtls_mpi_init( &T );
512c2c66affSColin Finck 
513c2c66affSColin Finck     slen = strlen( s );
514c2c66affSColin Finck 
515c2c66affSColin Finck     if( radix == 16 )
516c2c66affSColin Finck     {
517c2c66affSColin Finck         if( slen > MPI_SIZE_T_MAX >> 2 )
518c2c66affSColin Finck             return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
519c2c66affSColin Finck 
520c2c66affSColin Finck         n = BITS_TO_LIMBS( slen << 2 );
521c2c66affSColin Finck 
522c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
523c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
524c2c66affSColin Finck 
525c2c66affSColin Finck         for( i = slen, j = 0; i > 0; i--, j++ )
526c2c66affSColin Finck         {
527c2c66affSColin Finck             if( i == 1 && s[i - 1] == '-' )
528c2c66affSColin Finck             {
529c2c66affSColin Finck                 X->s = -1;
530c2c66affSColin Finck                 break;
531c2c66affSColin Finck             }
532c2c66affSColin Finck 
533c2c66affSColin Finck             MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
534c2c66affSColin Finck             X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
535c2c66affSColin Finck         }
536c2c66affSColin Finck     }
537c2c66affSColin Finck     else
538c2c66affSColin Finck     {
539c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
540c2c66affSColin Finck 
541c2c66affSColin Finck         for( i = 0; i < slen; i++ )
542c2c66affSColin Finck         {
543c2c66affSColin Finck             if( i == 0 && s[i] == '-' )
544c2c66affSColin Finck             {
545c2c66affSColin Finck                 X->s = -1;
546c2c66affSColin Finck                 continue;
547c2c66affSColin Finck             }
548c2c66affSColin Finck 
549c2c66affSColin Finck             MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
550c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
551c2c66affSColin Finck 
552c2c66affSColin Finck             if( X->s == 1 )
553c2c66affSColin Finck             {
554c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
555c2c66affSColin Finck             }
556c2c66affSColin Finck             else
557c2c66affSColin Finck             {
558c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
559c2c66affSColin Finck             }
560c2c66affSColin Finck         }
561c2c66affSColin Finck     }
562c2c66affSColin Finck 
563c2c66affSColin Finck cleanup:
564c2c66affSColin Finck 
565c2c66affSColin Finck     mbedtls_mpi_free( &T );
566c2c66affSColin Finck 
567c2c66affSColin Finck     return( ret );
568c2c66affSColin Finck }
569c2c66affSColin Finck 
570c2c66affSColin Finck /*
571ca86ee9cSThomas Faber  * Helper to write the digits high-order first.
572c2c66affSColin Finck  */
573ca86ee9cSThomas Faber static int mpi_write_hlp( mbedtls_mpi *X, int radix,
574ca86ee9cSThomas Faber                           char **p, const size_t buflen )
575c2c66affSColin Finck {
576c2c66affSColin Finck     int ret;
577c2c66affSColin Finck     mbedtls_mpi_uint r;
578ca86ee9cSThomas Faber     size_t length = 0;
579ca86ee9cSThomas Faber     char *p_end = *p + buflen;
580c2c66affSColin Finck 
581ca86ee9cSThomas Faber     do
582ca86ee9cSThomas Faber     {
583ca86ee9cSThomas Faber         if( length >= buflen )
584ca86ee9cSThomas Faber         {
585ca86ee9cSThomas Faber             return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
586ca86ee9cSThomas Faber         }
587c2c66affSColin Finck 
588c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
589c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
590ca86ee9cSThomas Faber         /*
591ca86ee9cSThomas Faber          * Write the residue in the current position, as an ASCII character.
592ca86ee9cSThomas Faber          */
593ca86ee9cSThomas Faber         if( r < 0xA )
594ca86ee9cSThomas Faber             *(--p_end) = (char)( '0' + r );
595c2c66affSColin Finck         else
596ca86ee9cSThomas Faber             *(--p_end) = (char)( 'A' + ( r - 0xA ) );
597ca86ee9cSThomas Faber 
598ca86ee9cSThomas Faber         length++;
599ca86ee9cSThomas Faber     } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
600ca86ee9cSThomas Faber 
601ca86ee9cSThomas Faber     memmove( *p, p_end, length );
602ca86ee9cSThomas Faber     *p += length;
603c2c66affSColin Finck 
604c2c66affSColin Finck cleanup:
605c2c66affSColin Finck 
606c2c66affSColin Finck     return( ret );
607c2c66affSColin Finck }
608c2c66affSColin Finck 
609c2c66affSColin Finck /*
610c2c66affSColin Finck  * Export into an ASCII string
611c2c66affSColin Finck  */
612c2c66affSColin Finck int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
613c2c66affSColin Finck                               char *buf, size_t buflen, size_t *olen )
614c2c66affSColin Finck {
615c2c66affSColin Finck     int ret = 0;
616c2c66affSColin Finck     size_t n;
617c2c66affSColin Finck     char *p;
618c2c66affSColin Finck     mbedtls_mpi T;
619*cbda039fSThomas Faber     MPI_VALIDATE_RET( X    != NULL );
620*cbda039fSThomas Faber     MPI_VALIDATE_RET( olen != NULL );
621*cbda039fSThomas Faber     MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
622c2c66affSColin Finck 
623c2c66affSColin Finck     if( radix < 2 || radix > 16 )
624c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
625c2c66affSColin Finck 
626430656f0SThomas Faber     n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
627430656f0SThomas Faber     if( radix >=  4 ) n >>= 1;   /* Number of 4-adic digits necessary to present
628430656f0SThomas Faber                                   * `n`. If radix > 4, this might be a strict
629430656f0SThomas Faber                                   * overapproximation of the number of
630430656f0SThomas Faber                                   * radix-adic digits needed to present `n`. */
631430656f0SThomas Faber     if( radix >= 16 ) n >>= 1;   /* Number of hexadecimal digits necessary to
632430656f0SThomas Faber                                   * present `n`. */
633430656f0SThomas Faber 
634430656f0SThomas Faber     n += 1; /* Terminating null byte */
635430656f0SThomas Faber     n += 1; /* Compensate for the divisions above, which round down `n`
636430656f0SThomas Faber              * in case it's not even. */
637430656f0SThomas Faber     n += 1; /* Potential '-'-sign. */
638430656f0SThomas Faber     n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
639430656f0SThomas Faber                      * which always uses an even number of hex-digits. */
640c2c66affSColin Finck 
641c2c66affSColin Finck     if( buflen < n )
642c2c66affSColin Finck     {
643c2c66affSColin Finck         *olen = n;
644c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
645c2c66affSColin Finck     }
646c2c66affSColin Finck 
647c2c66affSColin Finck     p = buf;
648c2c66affSColin Finck     mbedtls_mpi_init( &T );
649c2c66affSColin Finck 
650c2c66affSColin Finck     if( X->s == -1 )
651430656f0SThomas Faber     {
652c2c66affSColin Finck         *p++ = '-';
653430656f0SThomas Faber         buflen--;
654430656f0SThomas Faber     }
655c2c66affSColin Finck 
656c2c66affSColin Finck     if( radix == 16 )
657c2c66affSColin Finck     {
658c2c66affSColin Finck         int c;
659c2c66affSColin Finck         size_t i, j, k;
660c2c66affSColin Finck 
661c2c66affSColin Finck         for( i = X->n, k = 0; i > 0; i-- )
662c2c66affSColin Finck         {
663c2c66affSColin Finck             for( j = ciL; j > 0; j-- )
664c2c66affSColin Finck             {
665c2c66affSColin Finck                 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
666c2c66affSColin Finck 
667c2c66affSColin Finck                 if( c == 0 && k == 0 && ( i + j ) != 2 )
668c2c66affSColin Finck                     continue;
669c2c66affSColin Finck 
670c2c66affSColin Finck                 *(p++) = "0123456789ABCDEF" [c / 16];
671c2c66affSColin Finck                 *(p++) = "0123456789ABCDEF" [c % 16];
672c2c66affSColin Finck                 k = 1;
673c2c66affSColin Finck             }
674c2c66affSColin Finck         }
675c2c66affSColin Finck     }
676c2c66affSColin Finck     else
677c2c66affSColin Finck     {
678c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
679c2c66affSColin Finck 
680c2c66affSColin Finck         if( T.s == -1 )
681c2c66affSColin Finck             T.s = 1;
682c2c66affSColin Finck 
683ca86ee9cSThomas Faber         MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
684c2c66affSColin Finck     }
685c2c66affSColin Finck 
686c2c66affSColin Finck     *p++ = '\0';
687c2c66affSColin Finck     *olen = p - buf;
688c2c66affSColin Finck 
689c2c66affSColin Finck cleanup:
690c2c66affSColin Finck 
691c2c66affSColin Finck     mbedtls_mpi_free( &T );
692c2c66affSColin Finck 
693c2c66affSColin Finck     return( ret );
694c2c66affSColin Finck }
695c2c66affSColin Finck 
696c2c66affSColin Finck #if defined(MBEDTLS_FS_IO)
697c2c66affSColin Finck /*
698c2c66affSColin Finck  * Read X from an opened file
699c2c66affSColin Finck  */
700c2c66affSColin Finck int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
701c2c66affSColin Finck {
702c2c66affSColin Finck     mbedtls_mpi_uint d;
703c2c66affSColin Finck     size_t slen;
704c2c66affSColin Finck     char *p;
705c2c66affSColin Finck     /*
706c2c66affSColin Finck      * Buffer should have space for (short) label and decimal formatted MPI,
707c2c66affSColin Finck      * newline characters and '\0'
708c2c66affSColin Finck      */
709c2c66affSColin Finck     char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
710c2c66affSColin Finck 
711*cbda039fSThomas Faber     MPI_VALIDATE_RET( X   != NULL );
712*cbda039fSThomas Faber     MPI_VALIDATE_RET( fin != NULL );
713*cbda039fSThomas Faber 
714*cbda039fSThomas Faber     if( radix < 2 || radix > 16 )
715*cbda039fSThomas Faber         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
716*cbda039fSThomas Faber 
717c2c66affSColin Finck     memset( s, 0, sizeof( s ) );
718c2c66affSColin Finck     if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
719c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
720c2c66affSColin Finck 
721c2c66affSColin Finck     slen = strlen( s );
722c2c66affSColin Finck     if( slen == sizeof( s ) - 2 )
723c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
724c2c66affSColin Finck 
725c2c66affSColin Finck     if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
726c2c66affSColin Finck     if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
727c2c66affSColin Finck 
728c2c66affSColin Finck     p = s + slen;
729c2c66affSColin Finck     while( p-- > s )
730c2c66affSColin Finck         if( mpi_get_digit( &d, radix, *p ) != 0 )
731c2c66affSColin Finck             break;
732c2c66affSColin Finck 
733c2c66affSColin Finck     return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
734c2c66affSColin Finck }
735c2c66affSColin Finck 
736c2c66affSColin Finck /*
737c2c66affSColin Finck  * Write X into an opened file (or stdout if fout == NULL)
738c2c66affSColin Finck  */
739c2c66affSColin Finck int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
740c2c66affSColin Finck {
741c2c66affSColin Finck     int ret;
742c2c66affSColin Finck     size_t n, slen, plen;
743c2c66affSColin Finck     /*
744c2c66affSColin Finck      * Buffer should have space for (short) label and decimal formatted MPI,
745c2c66affSColin Finck      * newline characters and '\0'
746c2c66affSColin Finck      */
747c2c66affSColin Finck     char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
748*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
749*cbda039fSThomas Faber 
750*cbda039fSThomas Faber     if( radix < 2 || radix > 16 )
751*cbda039fSThomas Faber         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
752c2c66affSColin Finck 
753c2c66affSColin Finck     memset( s, 0, sizeof( s ) );
754c2c66affSColin Finck 
755c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
756c2c66affSColin Finck 
757c2c66affSColin Finck     if( p == NULL ) p = "";
758c2c66affSColin Finck 
759c2c66affSColin Finck     plen = strlen( p );
760c2c66affSColin Finck     slen = strlen( s );
761c2c66affSColin Finck     s[slen++] = '\r';
762c2c66affSColin Finck     s[slen++] = '\n';
763c2c66affSColin Finck 
764c2c66affSColin Finck     if( fout != NULL )
765c2c66affSColin Finck     {
766c2c66affSColin Finck         if( fwrite( p, 1, plen, fout ) != plen ||
767c2c66affSColin Finck             fwrite( s, 1, slen, fout ) != slen )
768c2c66affSColin Finck             return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
769c2c66affSColin Finck     }
770c2c66affSColin Finck     else
771c2c66affSColin Finck         mbedtls_printf( "%s%s", p, s );
772c2c66affSColin Finck 
773c2c66affSColin Finck cleanup:
774c2c66affSColin Finck 
775c2c66affSColin Finck     return( ret );
776c2c66affSColin Finck }
777c2c66affSColin Finck #endif /* MBEDTLS_FS_IO */
778c2c66affSColin Finck 
779*cbda039fSThomas Faber 
780*cbda039fSThomas Faber /* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
781*cbda039fSThomas Faber  * into the storage form used by mbedtls_mpi. */
782*cbda039fSThomas Faber 
783*cbda039fSThomas Faber static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
784*cbda039fSThomas Faber {
785*cbda039fSThomas Faber     uint8_t i;
786*cbda039fSThomas Faber     unsigned char *x_ptr;
787*cbda039fSThomas Faber     mbedtls_mpi_uint tmp = 0;
788*cbda039fSThomas Faber 
789*cbda039fSThomas Faber     for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
790*cbda039fSThomas Faber     {
791*cbda039fSThomas Faber         tmp <<= CHAR_BIT;
792*cbda039fSThomas Faber         tmp |= (mbedtls_mpi_uint) *x_ptr;
793*cbda039fSThomas Faber     }
794*cbda039fSThomas Faber 
795*cbda039fSThomas Faber     return( tmp );
796*cbda039fSThomas Faber }
797*cbda039fSThomas Faber 
798*cbda039fSThomas Faber static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
799*cbda039fSThomas Faber {
800*cbda039fSThomas Faber #if defined(__BYTE_ORDER__)
801*cbda039fSThomas Faber 
802*cbda039fSThomas Faber /* Nothing to do on bigendian systems. */
803*cbda039fSThomas Faber #if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
804*cbda039fSThomas Faber     return( x );
805*cbda039fSThomas Faber #endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
806*cbda039fSThomas Faber 
807*cbda039fSThomas Faber #if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
808*cbda039fSThomas Faber 
809*cbda039fSThomas Faber /* For GCC and Clang, have builtins for byte swapping. */
810*cbda039fSThomas Faber #if defined(__GNUC__) && defined(__GNUC_PREREQ)
811*cbda039fSThomas Faber #if __GNUC_PREREQ(4,3)
812*cbda039fSThomas Faber #define have_bswap
813*cbda039fSThomas Faber #endif
814*cbda039fSThomas Faber #endif
815*cbda039fSThomas Faber 
816*cbda039fSThomas Faber #if defined(__clang__) && defined(__has_builtin)
817*cbda039fSThomas Faber #if __has_builtin(__builtin_bswap32)  &&                 \
818*cbda039fSThomas Faber     __has_builtin(__builtin_bswap64)
819*cbda039fSThomas Faber #define have_bswap
820*cbda039fSThomas Faber #endif
821*cbda039fSThomas Faber #endif
822*cbda039fSThomas Faber 
823*cbda039fSThomas Faber #if defined(have_bswap)
824*cbda039fSThomas Faber     /* The compiler is hopefully able to statically evaluate this! */
825*cbda039fSThomas Faber     switch( sizeof(mbedtls_mpi_uint) )
826*cbda039fSThomas Faber     {
827*cbda039fSThomas Faber         case 4:
828*cbda039fSThomas Faber             return( __builtin_bswap32(x) );
829*cbda039fSThomas Faber         case 8:
830*cbda039fSThomas Faber             return( __builtin_bswap64(x) );
831*cbda039fSThomas Faber     }
832*cbda039fSThomas Faber #endif
833*cbda039fSThomas Faber #endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
834*cbda039fSThomas Faber #endif /* __BYTE_ORDER__ */
835*cbda039fSThomas Faber 
836*cbda039fSThomas Faber     /* Fall back to C-based reordering if we don't know the byte order
837*cbda039fSThomas Faber      * or we couldn't use a compiler-specific builtin. */
838*cbda039fSThomas Faber     return( mpi_uint_bigendian_to_host_c( x ) );
839*cbda039fSThomas Faber }
840*cbda039fSThomas Faber 
841*cbda039fSThomas Faber static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
842*cbda039fSThomas Faber {
843*cbda039fSThomas Faber     mbedtls_mpi_uint *cur_limb_left;
844*cbda039fSThomas Faber     mbedtls_mpi_uint *cur_limb_right;
845*cbda039fSThomas Faber     if( limbs == 0 )
846*cbda039fSThomas Faber         return;
847*cbda039fSThomas Faber 
848*cbda039fSThomas Faber     /*
849*cbda039fSThomas Faber      * Traverse limbs and
850*cbda039fSThomas Faber      * - adapt byte-order in each limb
851*cbda039fSThomas Faber      * - swap the limbs themselves.
852*cbda039fSThomas Faber      * For that, simultaneously traverse the limbs from left to right
853*cbda039fSThomas Faber      * and from right to left, as long as the left index is not bigger
854*cbda039fSThomas Faber      * than the right index (it's not a problem if limbs is odd and the
855*cbda039fSThomas Faber      * indices coincide in the last iteration).
856*cbda039fSThomas Faber      */
857*cbda039fSThomas Faber     for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
858*cbda039fSThomas Faber          cur_limb_left <= cur_limb_right;
859*cbda039fSThomas Faber          cur_limb_left++, cur_limb_right-- )
860*cbda039fSThomas Faber     {
861*cbda039fSThomas Faber         mbedtls_mpi_uint tmp;
862*cbda039fSThomas Faber         /* Note that if cur_limb_left == cur_limb_right,
863*cbda039fSThomas Faber          * this code effectively swaps the bytes only once. */
864*cbda039fSThomas Faber         tmp             = mpi_uint_bigendian_to_host( *cur_limb_left  );
865*cbda039fSThomas Faber         *cur_limb_left  = mpi_uint_bigendian_to_host( *cur_limb_right );
866*cbda039fSThomas Faber         *cur_limb_right = tmp;
867*cbda039fSThomas Faber     }
868*cbda039fSThomas Faber }
869*cbda039fSThomas Faber 
870c2c66affSColin Finck /*
871c2c66affSColin Finck  * Import X from unsigned binary data, big endian
872c2c66affSColin Finck  */
873c2c66affSColin Finck int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
874c2c66affSColin Finck {
875c2c66affSColin Finck     int ret;
876d9e6c9b5SThomas Faber     size_t const limbs    = CHARS_TO_LIMBS( buflen );
877*cbda039fSThomas Faber     size_t const overhead = ( limbs * ciL ) - buflen;
878*cbda039fSThomas Faber     unsigned char *Xp;
879*cbda039fSThomas Faber 
880*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
881*cbda039fSThomas Faber     MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
882c2c66affSColin Finck 
883d9e6c9b5SThomas Faber     /* Ensure that target MPI has exactly the necessary number of limbs */
884d9e6c9b5SThomas Faber     if( X->n != limbs )
885d9e6c9b5SThomas Faber     {
886d9e6c9b5SThomas Faber         mbedtls_mpi_free( X );
887d9e6c9b5SThomas Faber         mbedtls_mpi_init( X );
888d9e6c9b5SThomas Faber         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
889d9e6c9b5SThomas Faber     }
890c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
891c2c66affSColin Finck 
892*cbda039fSThomas Faber     /* Avoid calling `memcpy` with NULL source argument,
893*cbda039fSThomas Faber      * even if buflen is 0. */
894*cbda039fSThomas Faber     if( buf != NULL )
895*cbda039fSThomas Faber     {
896*cbda039fSThomas Faber         Xp = (unsigned char*) X->p;
897*cbda039fSThomas Faber         memcpy( Xp + overhead, buf, buflen );
898*cbda039fSThomas Faber 
899*cbda039fSThomas Faber         mpi_bigendian_to_host( X->p, limbs );
900*cbda039fSThomas Faber     }
901c2c66affSColin Finck 
902c2c66affSColin Finck cleanup:
903c2c66affSColin Finck 
904c2c66affSColin Finck     return( ret );
905c2c66affSColin Finck }
906c2c66affSColin Finck 
907c2c66affSColin Finck /*
908c2c66affSColin Finck  * Export X into unsigned binary data, big endian
909c2c66affSColin Finck  */
9100ba5bc40SThomas Faber int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
9110ba5bc40SThomas Faber                               unsigned char *buf, size_t buflen )
912c2c66affSColin Finck {
913*cbda039fSThomas Faber     size_t stored_bytes;
9140ba5bc40SThomas Faber     size_t bytes_to_copy;
9150ba5bc40SThomas Faber     unsigned char *p;
9160ba5bc40SThomas Faber     size_t i;
917c2c66affSColin Finck 
918*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
919*cbda039fSThomas Faber     MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
920*cbda039fSThomas Faber 
921*cbda039fSThomas Faber     stored_bytes = X->n * ciL;
922*cbda039fSThomas Faber 
9230ba5bc40SThomas Faber     if( stored_bytes < buflen )
9240ba5bc40SThomas Faber     {
9250ba5bc40SThomas Faber         /* There is enough space in the output buffer. Write initial
9260ba5bc40SThomas Faber          * null bytes and record the position at which to start
9270ba5bc40SThomas Faber          * writing the significant bytes. In this case, the execution
9280ba5bc40SThomas Faber          * trace of this function does not depend on the value of the
9290ba5bc40SThomas Faber          * number. */
9300ba5bc40SThomas Faber         bytes_to_copy = stored_bytes;
9310ba5bc40SThomas Faber         p = buf + buflen - stored_bytes;
9320ba5bc40SThomas Faber         memset( buf, 0, buflen - stored_bytes );
9330ba5bc40SThomas Faber     }
9340ba5bc40SThomas Faber     else
9350ba5bc40SThomas Faber     {
9360ba5bc40SThomas Faber         /* The output buffer is smaller than the allocated size of X.
9370ba5bc40SThomas Faber          * However X may fit if its leading bytes are zero. */
9380ba5bc40SThomas Faber         bytes_to_copy = buflen;
9390ba5bc40SThomas Faber         p = buf;
9400ba5bc40SThomas Faber         for( i = bytes_to_copy; i < stored_bytes; i++ )
9410ba5bc40SThomas Faber         {
9420ba5bc40SThomas Faber             if( GET_BYTE( X, i ) != 0 )
943c2c66affSColin Finck                 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
9440ba5bc40SThomas Faber         }
9450ba5bc40SThomas Faber     }
946c2c66affSColin Finck 
9470ba5bc40SThomas Faber     for( i = 0; i < bytes_to_copy; i++ )
9480ba5bc40SThomas Faber         p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
949c2c66affSColin Finck 
950c2c66affSColin Finck     return( 0 );
951c2c66affSColin Finck }
952c2c66affSColin Finck 
953c2c66affSColin Finck /*
954c2c66affSColin Finck  * Left-shift: X <<= count
955c2c66affSColin Finck  */
956c2c66affSColin Finck int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
957c2c66affSColin Finck {
958c2c66affSColin Finck     int ret;
959c2c66affSColin Finck     size_t i, v0, t1;
960c2c66affSColin Finck     mbedtls_mpi_uint r0 = 0, r1;
961*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
962c2c66affSColin Finck 
963c2c66affSColin Finck     v0 = count / (biL    );
964c2c66affSColin Finck     t1 = count & (biL - 1);
965c2c66affSColin Finck 
966c2c66affSColin Finck     i = mbedtls_mpi_bitlen( X ) + count;
967c2c66affSColin Finck 
968c2c66affSColin Finck     if( X->n * biL < i )
969c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
970c2c66affSColin Finck 
971c2c66affSColin Finck     ret = 0;
972c2c66affSColin Finck 
973c2c66affSColin Finck     /*
974c2c66affSColin Finck      * shift by count / limb_size
975c2c66affSColin Finck      */
976c2c66affSColin Finck     if( v0 > 0 )
977c2c66affSColin Finck     {
978c2c66affSColin Finck         for( i = X->n; i > v0; i-- )
979c2c66affSColin Finck             X->p[i - 1] = X->p[i - v0 - 1];
980c2c66affSColin Finck 
981c2c66affSColin Finck         for( ; i > 0; i-- )
982c2c66affSColin Finck             X->p[i - 1] = 0;
983c2c66affSColin Finck     }
984c2c66affSColin Finck 
985c2c66affSColin Finck     /*
986c2c66affSColin Finck      * shift by count % limb_size
987c2c66affSColin Finck      */
988c2c66affSColin Finck     if( t1 > 0 )
989c2c66affSColin Finck     {
990c2c66affSColin Finck         for( i = v0; i < X->n; i++ )
991c2c66affSColin Finck         {
992c2c66affSColin Finck             r1 = X->p[i] >> (biL - t1);
993c2c66affSColin Finck             X->p[i] <<= t1;
994c2c66affSColin Finck             X->p[i] |= r0;
995c2c66affSColin Finck             r0 = r1;
996c2c66affSColin Finck         }
997c2c66affSColin Finck     }
998c2c66affSColin Finck 
999c2c66affSColin Finck cleanup:
1000c2c66affSColin Finck 
1001c2c66affSColin Finck     return( ret );
1002c2c66affSColin Finck }
1003c2c66affSColin Finck 
1004c2c66affSColin Finck /*
1005c2c66affSColin Finck  * Right-shift: X >>= count
1006c2c66affSColin Finck  */
1007c2c66affSColin Finck int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
1008c2c66affSColin Finck {
1009c2c66affSColin Finck     size_t i, v0, v1;
1010c2c66affSColin Finck     mbedtls_mpi_uint r0 = 0, r1;
1011*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
1012c2c66affSColin Finck 
1013c2c66affSColin Finck     v0 = count /  biL;
1014c2c66affSColin Finck     v1 = count & (biL - 1);
1015c2c66affSColin Finck 
1016c2c66affSColin Finck     if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
1017c2c66affSColin Finck         return mbedtls_mpi_lset( X, 0 );
1018c2c66affSColin Finck 
1019c2c66affSColin Finck     /*
1020c2c66affSColin Finck      * shift by count / limb_size
1021c2c66affSColin Finck      */
1022c2c66affSColin Finck     if( v0 > 0 )
1023c2c66affSColin Finck     {
1024c2c66affSColin Finck         for( i = 0; i < X->n - v0; i++ )
1025c2c66affSColin Finck             X->p[i] = X->p[i + v0];
1026c2c66affSColin Finck 
1027c2c66affSColin Finck         for( ; i < X->n; i++ )
1028c2c66affSColin Finck             X->p[i] = 0;
1029c2c66affSColin Finck     }
1030c2c66affSColin Finck 
1031c2c66affSColin Finck     /*
1032c2c66affSColin Finck      * shift by count % limb_size
1033c2c66affSColin Finck      */
1034c2c66affSColin Finck     if( v1 > 0 )
1035c2c66affSColin Finck     {
1036c2c66affSColin Finck         for( i = X->n; i > 0; i-- )
1037c2c66affSColin Finck         {
1038c2c66affSColin Finck             r1 = X->p[i - 1] << (biL - v1);
1039c2c66affSColin Finck             X->p[i - 1] >>= v1;
1040c2c66affSColin Finck             X->p[i - 1] |= r0;
1041c2c66affSColin Finck             r0 = r1;
1042c2c66affSColin Finck         }
1043c2c66affSColin Finck     }
1044c2c66affSColin Finck 
1045c2c66affSColin Finck     return( 0 );
1046c2c66affSColin Finck }
1047c2c66affSColin Finck 
1048c2c66affSColin Finck /*
1049c2c66affSColin Finck  * Compare unsigned values
1050c2c66affSColin Finck  */
1051c2c66affSColin Finck int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
1052c2c66affSColin Finck {
1053c2c66affSColin Finck     size_t i, j;
1054*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
1055*cbda039fSThomas Faber     MPI_VALIDATE_RET( Y != NULL );
1056c2c66affSColin Finck 
1057c2c66affSColin Finck     for( i = X->n; i > 0; i-- )
1058c2c66affSColin Finck         if( X->p[i - 1] != 0 )
1059c2c66affSColin Finck             break;
1060c2c66affSColin Finck 
1061c2c66affSColin Finck     for( j = Y->n; j > 0; j-- )
1062c2c66affSColin Finck         if( Y->p[j - 1] != 0 )
1063c2c66affSColin Finck             break;
1064c2c66affSColin Finck 
1065c2c66affSColin Finck     if( i == 0 && j == 0 )
1066c2c66affSColin Finck         return( 0 );
1067c2c66affSColin Finck 
1068c2c66affSColin Finck     if( i > j ) return(  1 );
1069c2c66affSColin Finck     if( j > i ) return( -1 );
1070c2c66affSColin Finck 
1071c2c66affSColin Finck     for( ; i > 0; i-- )
1072c2c66affSColin Finck     {
1073c2c66affSColin Finck         if( X->p[i - 1] > Y->p[i - 1] ) return(  1 );
1074c2c66affSColin Finck         if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
1075c2c66affSColin Finck     }
1076c2c66affSColin Finck 
1077c2c66affSColin Finck     return( 0 );
1078c2c66affSColin Finck }
1079c2c66affSColin Finck 
1080c2c66affSColin Finck /*
1081c2c66affSColin Finck  * Compare signed values
1082c2c66affSColin Finck  */
1083c2c66affSColin Finck int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
1084c2c66affSColin Finck {
1085c2c66affSColin Finck     size_t i, j;
1086*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
1087*cbda039fSThomas Faber     MPI_VALIDATE_RET( Y != NULL );
1088c2c66affSColin Finck 
1089c2c66affSColin Finck     for( i = X->n; i > 0; i-- )
1090c2c66affSColin Finck         if( X->p[i - 1] != 0 )
1091c2c66affSColin Finck             break;
1092c2c66affSColin Finck 
1093c2c66affSColin Finck     for( j = Y->n; j > 0; j-- )
1094c2c66affSColin Finck         if( Y->p[j - 1] != 0 )
1095c2c66affSColin Finck             break;
1096c2c66affSColin Finck 
1097c2c66affSColin Finck     if( i == 0 && j == 0 )
1098c2c66affSColin Finck         return( 0 );
1099c2c66affSColin Finck 
1100c2c66affSColin Finck     if( i > j ) return(  X->s );
1101c2c66affSColin Finck     if( j > i ) return( -Y->s );
1102c2c66affSColin Finck 
1103c2c66affSColin Finck     if( X->s > 0 && Y->s < 0 ) return(  1 );
1104c2c66affSColin Finck     if( Y->s > 0 && X->s < 0 ) return( -1 );
1105c2c66affSColin Finck 
1106c2c66affSColin Finck     for( ; i > 0; i-- )
1107c2c66affSColin Finck     {
1108c2c66affSColin Finck         if( X->p[i - 1] > Y->p[i - 1] ) return(  X->s );
1109c2c66affSColin Finck         if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
1110c2c66affSColin Finck     }
1111c2c66affSColin Finck 
1112c2c66affSColin Finck     return( 0 );
1113c2c66affSColin Finck }
1114c2c66affSColin Finck 
1115d152519aSThomas Faber /** Decide if an integer is less than the other, without branches.
1116d152519aSThomas Faber  *
1117d152519aSThomas Faber  * \param x         First integer.
1118d152519aSThomas Faber  * \param y         Second integer.
1119d152519aSThomas Faber  *
1120d152519aSThomas Faber  * \return          1 if \p x is less than \p y, 0 otherwise
1121d152519aSThomas Faber  */
1122d152519aSThomas Faber static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1123d152519aSThomas Faber         const mbedtls_mpi_uint y )
1124d152519aSThomas Faber {
1125d152519aSThomas Faber     mbedtls_mpi_uint ret;
1126d152519aSThomas Faber     mbedtls_mpi_uint cond;
1127d152519aSThomas Faber 
1128d152519aSThomas Faber     /*
1129d152519aSThomas Faber      * Check if the most significant bits (MSB) of the operands are different.
1130d152519aSThomas Faber      */
1131d152519aSThomas Faber     cond = ( x ^ y );
1132d152519aSThomas Faber     /*
1133d152519aSThomas Faber      * If the MSB are the same then the difference x-y will be negative (and
1134d152519aSThomas Faber      * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1135d152519aSThomas Faber      */
1136d152519aSThomas Faber     ret = ( x - y ) & ~cond;
1137d152519aSThomas Faber     /*
1138d152519aSThomas Faber      * If the MSB are different, then the operand with the MSB of 1 is the
1139d152519aSThomas Faber      * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1140d152519aSThomas Faber      * the MSB of y is 0.)
1141d152519aSThomas Faber      */
1142d152519aSThomas Faber     ret |= y & cond;
1143d152519aSThomas Faber 
1144d152519aSThomas Faber 
1145d152519aSThomas Faber     ret = ret >> ( biL - 1 );
1146d152519aSThomas Faber 
1147d152519aSThomas Faber     return (unsigned) ret;
1148d152519aSThomas Faber }
1149d152519aSThomas Faber 
1150d152519aSThomas Faber /*
1151d152519aSThomas Faber  * Compare signed values in constant time
1152d152519aSThomas Faber  */
1153d152519aSThomas Faber int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1154d152519aSThomas Faber         unsigned *ret )
1155d152519aSThomas Faber {
1156d152519aSThomas Faber     size_t i;
1157d152519aSThomas Faber     /* The value of any of these variables is either 0 or 1 at all times. */
1158d152519aSThomas Faber     unsigned cond, done, X_is_negative, Y_is_negative;
1159d152519aSThomas Faber 
1160*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
1161*cbda039fSThomas Faber     MPI_VALIDATE_RET( Y != NULL );
1162*cbda039fSThomas Faber     MPI_VALIDATE_RET( ret != NULL );
1163*cbda039fSThomas Faber 
1164d152519aSThomas Faber     if( X->n != Y->n )
1165d152519aSThomas Faber         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1166d152519aSThomas Faber 
1167d152519aSThomas Faber     /*
1168d152519aSThomas Faber      * Set sign_N to 1 if N >= 0, 0 if N < 0.
1169d152519aSThomas Faber      * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
1170d152519aSThomas Faber      */
1171d152519aSThomas Faber     X_is_negative = ( X->s & 2 ) >> 1;
1172d152519aSThomas Faber     Y_is_negative = ( Y->s & 2 ) >> 1;
1173d152519aSThomas Faber 
1174d152519aSThomas Faber     /*
1175d152519aSThomas Faber      * If the signs are different, then the positive operand is the bigger.
1176d152519aSThomas Faber      * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1177d152519aSThomas Faber      * is false if X is positive (X_is_negative == 0).
1178d152519aSThomas Faber      */
1179d152519aSThomas Faber     cond = ( X_is_negative ^ Y_is_negative );
1180d152519aSThomas Faber     *ret = cond & X_is_negative;
1181d152519aSThomas Faber 
1182d152519aSThomas Faber     /*
1183d152519aSThomas Faber      * This is a constant-time function. We might have the result, but we still
1184d152519aSThomas Faber      * need to go through the loop. Record if we have the result already.
1185d152519aSThomas Faber      */
1186d152519aSThomas Faber     done = cond;
1187d152519aSThomas Faber 
1188d152519aSThomas Faber     for( i = X->n; i > 0; i-- )
1189d152519aSThomas Faber     {
1190d152519aSThomas Faber         /*
1191d152519aSThomas Faber          * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1192d152519aSThomas Faber          * X and Y are negative.
1193d152519aSThomas Faber          *
1194d152519aSThomas Faber          * Again even if we can make a decision, we just mark the result and
1195d152519aSThomas Faber          * the fact that we are done and continue looping.
1196d152519aSThomas Faber          */
1197d152519aSThomas Faber         cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1198d152519aSThomas Faber         *ret |= cond & ( 1 - done ) & X_is_negative;
1199d152519aSThomas Faber         done |= cond;
1200d152519aSThomas Faber 
1201d152519aSThomas Faber         /*
1202d152519aSThomas Faber          * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1203d152519aSThomas Faber          * X and Y are positive.
1204d152519aSThomas Faber          *
1205d152519aSThomas Faber          * Again even if we can make a decision, we just mark the result and
1206d152519aSThomas Faber          * the fact that we are done and continue looping.
1207d152519aSThomas Faber          */
1208d152519aSThomas Faber         cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1209d152519aSThomas Faber         *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
1210d152519aSThomas Faber         done |= cond;
1211d152519aSThomas Faber     }
1212d152519aSThomas Faber 
1213d152519aSThomas Faber     return( 0 );
1214d152519aSThomas Faber }
1215d152519aSThomas Faber 
1216c2c66affSColin Finck /*
1217c2c66affSColin Finck  * Compare signed values
1218c2c66affSColin Finck  */
1219c2c66affSColin Finck int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
1220c2c66affSColin Finck {
1221c2c66affSColin Finck     mbedtls_mpi Y;
1222c2c66affSColin Finck     mbedtls_mpi_uint p[1];
1223*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
1224c2c66affSColin Finck 
1225c2c66affSColin Finck     *p  = ( z < 0 ) ? -z : z;
1226c2c66affSColin Finck     Y.s = ( z < 0 ) ? -1 : 1;
1227c2c66affSColin Finck     Y.n = 1;
1228c2c66affSColin Finck     Y.p = p;
1229c2c66affSColin Finck 
1230c2c66affSColin Finck     return( mbedtls_mpi_cmp_mpi( X, &Y ) );
1231c2c66affSColin Finck }
1232c2c66affSColin Finck 
1233c2c66affSColin Finck /*
1234c2c66affSColin Finck  * Unsigned addition: X = |A| + |B|  (HAC 14.7)
1235c2c66affSColin Finck  */
1236c2c66affSColin Finck int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1237c2c66affSColin Finck {
1238c2c66affSColin Finck     int ret;
1239c2c66affSColin Finck     size_t i, j;
1240c2c66affSColin Finck     mbedtls_mpi_uint *o, *p, c, tmp;
1241*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
1242*cbda039fSThomas Faber     MPI_VALIDATE_RET( A != NULL );
1243*cbda039fSThomas Faber     MPI_VALIDATE_RET( B != NULL );
1244c2c66affSColin Finck 
1245c2c66affSColin Finck     if( X == B )
1246c2c66affSColin Finck     {
1247c2c66affSColin Finck         const mbedtls_mpi *T = A; A = X; B = T;
1248c2c66affSColin Finck     }
1249c2c66affSColin Finck 
1250c2c66affSColin Finck     if( X != A )
1251c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
1252c2c66affSColin Finck 
1253c2c66affSColin Finck     /*
1254c2c66affSColin Finck      * X should always be positive as a result of unsigned additions.
1255c2c66affSColin Finck      */
1256c2c66affSColin Finck     X->s = 1;
1257c2c66affSColin Finck 
1258c2c66affSColin Finck     for( j = B->n; j > 0; j-- )
1259c2c66affSColin Finck         if( B->p[j - 1] != 0 )
1260c2c66affSColin Finck             break;
1261c2c66affSColin Finck 
1262c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1263c2c66affSColin Finck 
1264c2c66affSColin Finck     o = B->p; p = X->p; c = 0;
1265c2c66affSColin Finck 
1266c2c66affSColin Finck     /*
1267c2c66affSColin Finck      * tmp is used because it might happen that p == o
1268c2c66affSColin Finck      */
1269c2c66affSColin Finck     for( i = 0; i < j; i++, o++, p++ )
1270c2c66affSColin Finck     {
1271c2c66affSColin Finck         tmp= *o;
1272c2c66affSColin Finck         *p +=  c; c  = ( *p <  c );
1273c2c66affSColin Finck         *p += tmp; c += ( *p < tmp );
1274c2c66affSColin Finck     }
1275c2c66affSColin Finck 
1276c2c66affSColin Finck     while( c != 0 )
1277c2c66affSColin Finck     {
1278c2c66affSColin Finck         if( i >= X->n )
1279c2c66affSColin Finck         {
1280c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
1281c2c66affSColin Finck             p = X->p + i;
1282c2c66affSColin Finck         }
1283c2c66affSColin Finck 
1284c2c66affSColin Finck         *p += c; c = ( *p < c ); i++; p++;
1285c2c66affSColin Finck     }
1286c2c66affSColin Finck 
1287c2c66affSColin Finck cleanup:
1288c2c66affSColin Finck 
1289c2c66affSColin Finck     return( ret );
1290c2c66affSColin Finck }
1291c2c66affSColin Finck 
1292292f67afSThomas Faber /**
1293292f67afSThomas Faber  * Helper for mbedtls_mpi subtraction.
1294292f67afSThomas Faber  *
1295292f67afSThomas Faber  * Calculate d - s where d and s have the same size.
1296292f67afSThomas Faber  * This function operates modulo (2^ciL)^n and returns the carry
1297292f67afSThomas Faber  * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise).
1298292f67afSThomas Faber  *
1299292f67afSThomas Faber  * \param n             Number of limbs of \p d and \p s.
1300292f67afSThomas Faber  * \param[in,out] d     On input, the left operand.
1301292f67afSThomas Faber  *                      On output, the result of the subtraction:
1302292f67afSThomas Faber  * \param[in] s         The right operand.
1303292f67afSThomas Faber  *
1304292f67afSThomas Faber  * \return              1 if `d < s`.
1305292f67afSThomas Faber  *                      0 if `d >= s`.
1306c2c66affSColin Finck  */
1307292f67afSThomas Faber static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1308292f67afSThomas Faber                                      mbedtls_mpi_uint *d,
1309292f67afSThomas Faber                                      const mbedtls_mpi_uint *s )
1310c2c66affSColin Finck {
1311c2c66affSColin Finck     size_t i;
1312c2c66affSColin Finck     mbedtls_mpi_uint c, z;
1313c2c66affSColin Finck 
1314c2c66affSColin Finck     for( i = c = 0; i < n; i++, s++, d++ )
1315c2c66affSColin Finck     {
1316c2c66affSColin Finck         z = ( *d <  c );     *d -=  c;
1317c2c66affSColin Finck         c = ( *d < *s ) + z; *d -= *s;
1318c2c66affSColin Finck     }
1319c2c66affSColin Finck 
1320292f67afSThomas Faber     return( c );
1321c2c66affSColin Finck }
1322c2c66affSColin Finck 
1323c2c66affSColin Finck /*
1324292f67afSThomas Faber  * Unsigned subtraction: X = |A| - |B|  (HAC 14.9, 14.10)
1325c2c66affSColin Finck  */
1326c2c66affSColin Finck int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1327c2c66affSColin Finck {
1328c2c66affSColin Finck     mbedtls_mpi TB;
1329c2c66affSColin Finck     int ret;
1330c2c66affSColin Finck     size_t n;
1331292f67afSThomas Faber     mbedtls_mpi_uint carry;
1332*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
1333*cbda039fSThomas Faber     MPI_VALIDATE_RET( A != NULL );
1334*cbda039fSThomas Faber     MPI_VALIDATE_RET( B != NULL );
1335c2c66affSColin Finck 
1336c2c66affSColin Finck     mbedtls_mpi_init( &TB );
1337c2c66affSColin Finck 
1338c2c66affSColin Finck     if( X == B )
1339c2c66affSColin Finck     {
1340c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
1341c2c66affSColin Finck         B = &TB;
1342c2c66affSColin Finck     }
1343c2c66affSColin Finck 
1344c2c66affSColin Finck     if( X != A )
1345c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
1346c2c66affSColin Finck 
1347c2c66affSColin Finck     /*
1348c2c66affSColin Finck      * X should always be positive as a result of unsigned subtractions.
1349c2c66affSColin Finck      */
1350c2c66affSColin Finck     X->s = 1;
1351c2c66affSColin Finck 
1352c2c66affSColin Finck     ret = 0;
1353c2c66affSColin Finck 
1354c2c66affSColin Finck     for( n = B->n; n > 0; n-- )
1355c2c66affSColin Finck         if( B->p[n - 1] != 0 )
1356c2c66affSColin Finck             break;
1357a01a8faaSThomas Faber     if( n > A->n )
1358a01a8faaSThomas Faber     {
1359a01a8faaSThomas Faber         /* B >= (2^ciL)^n > A */
1360a01a8faaSThomas Faber         ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1361a01a8faaSThomas Faber         goto cleanup;
1362a01a8faaSThomas Faber     }
1363c2c66affSColin Finck 
1364292f67afSThomas Faber     carry = mpi_sub_hlp( n, X->p, B->p );
1365292f67afSThomas Faber     if( carry != 0 )
1366292f67afSThomas Faber     {
1367292f67afSThomas Faber         /* Propagate the carry to the first nonzero limb of X. */
1368292f67afSThomas Faber         for( ; n < X->n && X->p[n] == 0; n++ )
1369292f67afSThomas Faber             --X->p[n];
1370292f67afSThomas Faber         /* If we ran out of space for the carry, it means that the result
1371292f67afSThomas Faber          * is negative. */
1372292f67afSThomas Faber         if( n == X->n )
13732e53fc8eSThomas Faber         {
13742e53fc8eSThomas Faber             ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
13752e53fc8eSThomas Faber             goto cleanup;
13762e53fc8eSThomas Faber         }
1377292f67afSThomas Faber         --X->p[n];
1378292f67afSThomas Faber     }
1379c2c66affSColin Finck 
1380c2c66affSColin Finck cleanup:
1381c2c66affSColin Finck 
1382c2c66affSColin Finck     mbedtls_mpi_free( &TB );
1383c2c66affSColin Finck 
1384c2c66affSColin Finck     return( ret );
1385c2c66affSColin Finck }
1386c2c66affSColin Finck 
1387c2c66affSColin Finck /*
1388c2c66affSColin Finck  * Signed addition: X = A + B
1389c2c66affSColin Finck  */
1390c2c66affSColin Finck int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1391c2c66affSColin Finck {
1392*cbda039fSThomas Faber     int ret, s;
1393*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
1394*cbda039fSThomas Faber     MPI_VALIDATE_RET( A != NULL );
1395*cbda039fSThomas Faber     MPI_VALIDATE_RET( B != NULL );
1396c2c66affSColin Finck 
1397*cbda039fSThomas Faber     s = A->s;
1398c2c66affSColin Finck     if( A->s * B->s < 0 )
1399c2c66affSColin Finck     {
1400c2c66affSColin Finck         if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
1401c2c66affSColin Finck         {
1402c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
1403c2c66affSColin Finck             X->s =  s;
1404c2c66affSColin Finck         }
1405c2c66affSColin Finck         else
1406c2c66affSColin Finck         {
1407c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
1408c2c66affSColin Finck             X->s = -s;
1409c2c66affSColin Finck         }
1410c2c66affSColin Finck     }
1411c2c66affSColin Finck     else
1412c2c66affSColin Finck     {
1413c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
1414c2c66affSColin Finck         X->s = s;
1415c2c66affSColin Finck     }
1416c2c66affSColin Finck 
1417c2c66affSColin Finck cleanup:
1418c2c66affSColin Finck 
1419c2c66affSColin Finck     return( ret );
1420c2c66affSColin Finck }
1421c2c66affSColin Finck 
1422c2c66affSColin Finck /*
1423c2c66affSColin Finck  * Signed subtraction: X = A - B
1424c2c66affSColin Finck  */
1425c2c66affSColin Finck int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1426c2c66affSColin Finck {
1427*cbda039fSThomas Faber     int ret, s;
1428*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
1429*cbda039fSThomas Faber     MPI_VALIDATE_RET( A != NULL );
1430*cbda039fSThomas Faber     MPI_VALIDATE_RET( B != NULL );
1431c2c66affSColin Finck 
1432*cbda039fSThomas Faber     s = A->s;
1433c2c66affSColin Finck     if( A->s * B->s > 0 )
1434c2c66affSColin Finck     {
1435c2c66affSColin Finck         if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
1436c2c66affSColin Finck         {
1437c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
1438c2c66affSColin Finck             X->s =  s;
1439c2c66affSColin Finck         }
1440c2c66affSColin Finck         else
1441c2c66affSColin Finck         {
1442c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
1443c2c66affSColin Finck             X->s = -s;
1444c2c66affSColin Finck         }
1445c2c66affSColin Finck     }
1446c2c66affSColin Finck     else
1447c2c66affSColin Finck     {
1448c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
1449c2c66affSColin Finck         X->s = s;
1450c2c66affSColin Finck     }
1451c2c66affSColin Finck 
1452c2c66affSColin Finck cleanup:
1453c2c66affSColin Finck 
1454c2c66affSColin Finck     return( ret );
1455c2c66affSColin Finck }
1456c2c66affSColin Finck 
1457c2c66affSColin Finck /*
1458c2c66affSColin Finck  * Signed addition: X = A + b
1459c2c66affSColin Finck  */
1460c2c66affSColin Finck int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1461c2c66affSColin Finck {
1462c2c66affSColin Finck     mbedtls_mpi _B;
1463c2c66affSColin Finck     mbedtls_mpi_uint p[1];
1464*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
1465*cbda039fSThomas Faber     MPI_VALIDATE_RET( A != NULL );
1466c2c66affSColin Finck 
1467c2c66affSColin Finck     p[0] = ( b < 0 ) ? -b : b;
1468c2c66affSColin Finck     _B.s = ( b < 0 ) ? -1 : 1;
1469c2c66affSColin Finck     _B.n = 1;
1470c2c66affSColin Finck     _B.p = p;
1471c2c66affSColin Finck 
1472c2c66affSColin Finck     return( mbedtls_mpi_add_mpi( X, A, &_B ) );
1473c2c66affSColin Finck }
1474c2c66affSColin Finck 
1475c2c66affSColin Finck /*
1476c2c66affSColin Finck  * Signed subtraction: X = A - b
1477c2c66affSColin Finck  */
1478c2c66affSColin Finck int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1479c2c66affSColin Finck {
1480c2c66affSColin Finck     mbedtls_mpi _B;
1481c2c66affSColin Finck     mbedtls_mpi_uint p[1];
1482*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
1483*cbda039fSThomas Faber     MPI_VALIDATE_RET( A != NULL );
1484c2c66affSColin Finck 
1485c2c66affSColin Finck     p[0] = ( b < 0 ) ? -b : b;
1486c2c66affSColin Finck     _B.s = ( b < 0 ) ? -1 : 1;
1487c2c66affSColin Finck     _B.n = 1;
1488c2c66affSColin Finck     _B.p = p;
1489c2c66affSColin Finck 
1490c2c66affSColin Finck     return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
1491c2c66affSColin Finck }
1492c2c66affSColin Finck 
1493c2c66affSColin Finck /*
1494c2c66affSColin Finck  * Helper for mbedtls_mpi multiplication
1495c2c66affSColin Finck  */
1496c2c66affSColin Finck static
1497c2c66affSColin Finck #if defined(__APPLE__) && defined(__arm__)
1498c2c66affSColin Finck /*
1499c2c66affSColin Finck  * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1500c2c66affSColin Finck  * appears to need this to prevent bad ARM code generation at -O3.
1501c2c66affSColin Finck  */
1502c2c66affSColin Finck __attribute__ ((noinline))
1503c2c66affSColin Finck #endif
1504c2c66affSColin Finck void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b )
1505c2c66affSColin Finck {
1506c2c66affSColin Finck     mbedtls_mpi_uint c = 0, t = 0;
1507c2c66affSColin Finck 
1508c2c66affSColin Finck #if defined(MULADDC_HUIT)
1509c2c66affSColin Finck     for( ; i >= 8; i -= 8 )
1510c2c66affSColin Finck     {
1511c2c66affSColin Finck         MULADDC_INIT
1512c2c66affSColin Finck         MULADDC_HUIT
1513c2c66affSColin Finck         MULADDC_STOP
1514c2c66affSColin Finck     }
1515c2c66affSColin Finck 
1516c2c66affSColin Finck     for( ; i > 0; i-- )
1517c2c66affSColin Finck     {
1518c2c66affSColin Finck         MULADDC_INIT
1519c2c66affSColin Finck         MULADDC_CORE
1520c2c66affSColin Finck         MULADDC_STOP
1521c2c66affSColin Finck     }
1522c2c66affSColin Finck #else /* MULADDC_HUIT */
1523c2c66affSColin Finck     for( ; i >= 16; i -= 16 )
1524c2c66affSColin Finck     {
1525c2c66affSColin Finck         MULADDC_INIT
1526c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1527c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1528c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1529c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1530c2c66affSColin Finck 
1531c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1532c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1533c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1534c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1535c2c66affSColin Finck         MULADDC_STOP
1536c2c66affSColin Finck     }
1537c2c66affSColin Finck 
1538c2c66affSColin Finck     for( ; i >= 8; i -= 8 )
1539c2c66affSColin Finck     {
1540c2c66affSColin Finck         MULADDC_INIT
1541c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1542c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1543c2c66affSColin Finck 
1544c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1545c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1546c2c66affSColin Finck         MULADDC_STOP
1547c2c66affSColin Finck     }
1548c2c66affSColin Finck 
1549c2c66affSColin Finck     for( ; i > 0; i-- )
1550c2c66affSColin Finck     {
1551c2c66affSColin Finck         MULADDC_INIT
1552c2c66affSColin Finck         MULADDC_CORE
1553c2c66affSColin Finck         MULADDC_STOP
1554c2c66affSColin Finck     }
1555c2c66affSColin Finck #endif /* MULADDC_HUIT */
1556c2c66affSColin Finck 
1557c2c66affSColin Finck     t++;
1558c2c66affSColin Finck 
1559c2c66affSColin Finck     do {
1560c2c66affSColin Finck         *d += c; c = ( *d < c ); d++;
1561c2c66affSColin Finck     }
1562c2c66affSColin Finck     while( c != 0 );
1563c2c66affSColin Finck }
1564c2c66affSColin Finck 
1565c2c66affSColin Finck /*
1566c2c66affSColin Finck  * Baseline multiplication: X = A * B  (HAC 14.12)
1567c2c66affSColin Finck  */
1568c2c66affSColin Finck int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1569c2c66affSColin Finck {
1570c2c66affSColin Finck     int ret;
1571c2c66affSColin Finck     size_t i, j;
1572c2c66affSColin Finck     mbedtls_mpi TA, TB;
1573*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
1574*cbda039fSThomas Faber     MPI_VALIDATE_RET( A != NULL );
1575*cbda039fSThomas Faber     MPI_VALIDATE_RET( B != NULL );
1576c2c66affSColin Finck 
1577c2c66affSColin Finck     mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
1578c2c66affSColin Finck 
1579c2c66affSColin Finck     if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1580c2c66affSColin Finck     if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
1581c2c66affSColin Finck 
1582c2c66affSColin Finck     for( i = A->n; i > 0; i-- )
1583c2c66affSColin Finck         if( A->p[i - 1] != 0 )
1584c2c66affSColin Finck             break;
1585c2c66affSColin Finck 
1586c2c66affSColin Finck     for( j = B->n; j > 0; j-- )
1587c2c66affSColin Finck         if( B->p[j - 1] != 0 )
1588c2c66affSColin Finck             break;
1589c2c66affSColin Finck 
1590c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1591c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
1592c2c66affSColin Finck 
1593*cbda039fSThomas Faber     for( ; j > 0; j-- )
1594*cbda039fSThomas Faber         mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
1595c2c66affSColin Finck 
1596c2c66affSColin Finck     X->s = A->s * B->s;
1597c2c66affSColin Finck 
1598c2c66affSColin Finck cleanup:
1599c2c66affSColin Finck 
1600c2c66affSColin Finck     mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
1601c2c66affSColin Finck 
1602c2c66affSColin Finck     return( ret );
1603c2c66affSColin Finck }
1604c2c66affSColin Finck 
1605c2c66affSColin Finck /*
1606c2c66affSColin Finck  * Baseline multiplication: X = A * b
1607c2c66affSColin Finck  */
1608c2c66affSColin Finck int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
1609c2c66affSColin Finck {
1610c2c66affSColin Finck     mbedtls_mpi _B;
1611c2c66affSColin Finck     mbedtls_mpi_uint p[1];
1612*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
1613*cbda039fSThomas Faber     MPI_VALIDATE_RET( A != NULL );
1614c2c66affSColin Finck 
1615c2c66affSColin Finck     _B.s = 1;
1616c2c66affSColin Finck     _B.n = 1;
1617c2c66affSColin Finck     _B.p = p;
1618c2c66affSColin Finck     p[0] = b;
1619c2c66affSColin Finck 
1620c2c66affSColin Finck     return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
1621c2c66affSColin Finck }
1622c2c66affSColin Finck 
1623c2c66affSColin Finck /*
1624c2c66affSColin Finck  * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1625c2c66affSColin Finck  * mbedtls_mpi_uint divisor, d
1626c2c66affSColin Finck  */
1627c2c66affSColin Finck static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1628c2c66affSColin Finck             mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
1629c2c66affSColin Finck {
1630c2c66affSColin Finck #if defined(MBEDTLS_HAVE_UDBL)
1631c2c66affSColin Finck     mbedtls_t_udbl dividend, quotient;
1632c2c66affSColin Finck #else
1633c2c66affSColin Finck     const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1634c2c66affSColin Finck     const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
1635c2c66affSColin Finck     mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1636c2c66affSColin Finck     mbedtls_mpi_uint u0_msw, u0_lsw;
1637c2c66affSColin Finck     size_t s;
1638c2c66affSColin Finck #endif
1639c2c66affSColin Finck 
1640c2c66affSColin Finck     /*
1641c2c66affSColin Finck      * Check for overflow
1642c2c66affSColin Finck      */
1643c2c66affSColin Finck     if( 0 == d || u1 >= d )
1644c2c66affSColin Finck     {
1645c2c66affSColin Finck         if (r != NULL) *r = ~0;
1646c2c66affSColin Finck 
1647c2c66affSColin Finck         return ( ~0 );
1648c2c66affSColin Finck     }
1649c2c66affSColin Finck 
1650c2c66affSColin Finck #if defined(MBEDTLS_HAVE_UDBL)
1651c2c66affSColin Finck     dividend  = (mbedtls_t_udbl) u1 << biL;
1652c2c66affSColin Finck     dividend |= (mbedtls_t_udbl) u0;
1653c2c66affSColin Finck     quotient = dividend / d;
1654c2c66affSColin Finck     if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1655c2c66affSColin Finck         quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1656c2c66affSColin Finck 
1657c2c66affSColin Finck     if( r != NULL )
1658c2c66affSColin Finck         *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
1659c2c66affSColin Finck 
1660c2c66affSColin Finck     return (mbedtls_mpi_uint) quotient;
1661c2c66affSColin Finck #else
1662c2c66affSColin Finck 
1663c2c66affSColin Finck     /*
1664c2c66affSColin Finck      * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1665c2c66affSColin Finck      *   Vol. 2 - Seminumerical Algorithms, Knuth
1666c2c66affSColin Finck      */
1667c2c66affSColin Finck 
1668c2c66affSColin Finck     /*
1669c2c66affSColin Finck      * Normalize the divisor, d, and dividend, u0, u1
1670c2c66affSColin Finck      */
1671c2c66affSColin Finck     s = mbedtls_clz( d );
1672c2c66affSColin Finck     d = d << s;
1673c2c66affSColin Finck 
1674c2c66affSColin Finck     u1 = u1 << s;
1675c2c66affSColin Finck     u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
1676c2c66affSColin Finck     u0 =  u0 << s;
1677c2c66affSColin Finck 
1678c2c66affSColin Finck     d1 = d >> biH;
1679c2c66affSColin Finck     d0 = d & uint_halfword_mask;
1680c2c66affSColin Finck 
1681c2c66affSColin Finck     u0_msw = u0 >> biH;
1682c2c66affSColin Finck     u0_lsw = u0 & uint_halfword_mask;
1683c2c66affSColin Finck 
1684c2c66affSColin Finck     /*
1685c2c66affSColin Finck      * Find the first quotient and remainder
1686c2c66affSColin Finck      */
1687c2c66affSColin Finck     q1 = u1 / d1;
1688c2c66affSColin Finck     r0 = u1 - d1 * q1;
1689c2c66affSColin Finck 
1690c2c66affSColin Finck     while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1691c2c66affSColin Finck     {
1692c2c66affSColin Finck         q1 -= 1;
1693c2c66affSColin Finck         r0 += d1;
1694c2c66affSColin Finck 
1695c2c66affSColin Finck         if ( r0 >= radix ) break;
1696c2c66affSColin Finck     }
1697c2c66affSColin Finck 
1698c2c66affSColin Finck     rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
1699c2c66affSColin Finck     q0 = rAX / d1;
1700c2c66affSColin Finck     r0 = rAX - q0 * d1;
1701c2c66affSColin Finck 
1702c2c66affSColin Finck     while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1703c2c66affSColin Finck     {
1704c2c66affSColin Finck         q0 -= 1;
1705c2c66affSColin Finck         r0 += d1;
1706c2c66affSColin Finck 
1707c2c66affSColin Finck         if ( r0 >= radix ) break;
1708c2c66affSColin Finck     }
1709c2c66affSColin Finck 
1710c2c66affSColin Finck     if (r != NULL)
1711c2c66affSColin Finck         *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
1712c2c66affSColin Finck 
1713c2c66affSColin Finck     quotient = q1 * radix + q0;
1714c2c66affSColin Finck 
1715c2c66affSColin Finck     return quotient;
1716c2c66affSColin Finck #endif
1717c2c66affSColin Finck }
1718c2c66affSColin Finck 
1719c2c66affSColin Finck /*
1720c2c66affSColin Finck  * Division by mbedtls_mpi: A = Q * B + R  (HAC 14.20)
1721c2c66affSColin Finck  */
1722*cbda039fSThomas Faber int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1723*cbda039fSThomas Faber                          const mbedtls_mpi *B )
1724c2c66affSColin Finck {
1725c2c66affSColin Finck     int ret;
1726c2c66affSColin Finck     size_t i, n, t, k;
1727c2c66affSColin Finck     mbedtls_mpi X, Y, Z, T1, T2;
1728*cbda039fSThomas Faber     MPI_VALIDATE_RET( A != NULL );
1729*cbda039fSThomas Faber     MPI_VALIDATE_RET( B != NULL );
1730c2c66affSColin Finck 
1731c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1732c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
1733c2c66affSColin Finck 
1734c2c66affSColin Finck     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1735c2c66affSColin Finck     mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
1736c2c66affSColin Finck 
1737c2c66affSColin Finck     if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1738c2c66affSColin Finck     {
1739c2c66affSColin Finck         if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1740c2c66affSColin Finck         if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
1741c2c66affSColin Finck         return( 0 );
1742c2c66affSColin Finck     }
1743c2c66affSColin Finck 
1744c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1745c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
1746c2c66affSColin Finck     X.s = Y.s = 1;
1747c2c66affSColin Finck 
1748c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1749c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z,  0 ) );
1750c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1751c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
1752c2c66affSColin Finck 
1753c2c66affSColin Finck     k = mbedtls_mpi_bitlen( &Y ) % biL;
1754c2c66affSColin Finck     if( k < biL - 1 )
1755c2c66affSColin Finck     {
1756c2c66affSColin Finck         k = biL - 1 - k;
1757c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1758c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
1759c2c66affSColin Finck     }
1760c2c66affSColin Finck     else k = 0;
1761c2c66affSColin Finck 
1762c2c66affSColin Finck     n = X.n - 1;
1763c2c66affSColin Finck     t = Y.n - 1;
1764c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
1765c2c66affSColin Finck 
1766c2c66affSColin Finck     while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
1767c2c66affSColin Finck     {
1768c2c66affSColin Finck         Z.p[n - t]++;
1769c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
1770c2c66affSColin Finck     }
1771c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
1772c2c66affSColin Finck 
1773c2c66affSColin Finck     for( i = n; i > t ; i-- )
1774c2c66affSColin Finck     {
1775c2c66affSColin Finck         if( X.p[i] >= Y.p[t] )
1776c2c66affSColin Finck             Z.p[i - t - 1] = ~0;
1777c2c66affSColin Finck         else
1778c2c66affSColin Finck         {
1779c2c66affSColin Finck             Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1780c2c66affSColin Finck                                                             Y.p[t], NULL);
1781c2c66affSColin Finck         }
1782c2c66affSColin Finck 
1783c2c66affSColin Finck         Z.p[i - t - 1]++;
1784c2c66affSColin Finck         do
1785c2c66affSColin Finck         {
1786c2c66affSColin Finck             Z.p[i - t - 1]--;
1787c2c66affSColin Finck 
1788c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
1789c2c66affSColin Finck             T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
1790c2c66affSColin Finck             T1.p[1] = Y.p[t];
1791c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1792c2c66affSColin Finck 
1793c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
1794c2c66affSColin Finck             T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1795c2c66affSColin Finck             T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1796c2c66affSColin Finck             T2.p[2] = X.p[i];
1797c2c66affSColin Finck         }
1798c2c66affSColin Finck         while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
1799c2c66affSColin Finck 
1800c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1801c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1,  biL * ( i - t - 1 ) ) );
1802c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
1803c2c66affSColin Finck 
1804c2c66affSColin Finck         if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
1805c2c66affSColin Finck         {
1806c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1807c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1808c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
1809c2c66affSColin Finck             Z.p[i - t - 1]--;
1810c2c66affSColin Finck         }
1811c2c66affSColin Finck     }
1812c2c66affSColin Finck 
1813c2c66affSColin Finck     if( Q != NULL )
1814c2c66affSColin Finck     {
1815c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
1816c2c66affSColin Finck         Q->s = A->s * B->s;
1817c2c66affSColin Finck     }
1818c2c66affSColin Finck 
1819c2c66affSColin Finck     if( R != NULL )
1820c2c66affSColin Finck     {
1821c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
1822c2c66affSColin Finck         X.s = A->s;
1823c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
1824c2c66affSColin Finck 
1825c2c66affSColin Finck         if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
1826c2c66affSColin Finck             R->s = 1;
1827c2c66affSColin Finck     }
1828c2c66affSColin Finck 
1829c2c66affSColin Finck cleanup:
1830c2c66affSColin Finck 
1831c2c66affSColin Finck     mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1832c2c66affSColin Finck     mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
1833c2c66affSColin Finck 
1834c2c66affSColin Finck     return( ret );
1835c2c66affSColin Finck }
1836c2c66affSColin Finck 
1837c2c66affSColin Finck /*
1838c2c66affSColin Finck  * Division by int: A = Q * b + R
1839c2c66affSColin Finck  */
1840*cbda039fSThomas Faber int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1841*cbda039fSThomas Faber                          const mbedtls_mpi *A,
1842*cbda039fSThomas Faber                          mbedtls_mpi_sint b )
1843c2c66affSColin Finck {
1844c2c66affSColin Finck     mbedtls_mpi _B;
1845c2c66affSColin Finck     mbedtls_mpi_uint p[1];
1846*cbda039fSThomas Faber     MPI_VALIDATE_RET( A != NULL );
1847c2c66affSColin Finck 
1848c2c66affSColin Finck     p[0] = ( b < 0 ) ? -b : b;
1849c2c66affSColin Finck     _B.s = ( b < 0 ) ? -1 : 1;
1850c2c66affSColin Finck     _B.n = 1;
1851c2c66affSColin Finck     _B.p = p;
1852c2c66affSColin Finck 
1853c2c66affSColin Finck     return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
1854c2c66affSColin Finck }
1855c2c66affSColin Finck 
1856c2c66affSColin Finck /*
1857c2c66affSColin Finck  * Modulo: R = A mod B
1858c2c66affSColin Finck  */
1859c2c66affSColin Finck int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
1860c2c66affSColin Finck {
1861c2c66affSColin Finck     int ret;
1862*cbda039fSThomas Faber     MPI_VALIDATE_RET( R != NULL );
1863*cbda039fSThomas Faber     MPI_VALIDATE_RET( A != NULL );
1864*cbda039fSThomas Faber     MPI_VALIDATE_RET( B != NULL );
1865c2c66affSColin Finck 
1866c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1867c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
1868c2c66affSColin Finck 
1869c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
1870c2c66affSColin Finck 
1871c2c66affSColin Finck     while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1872c2c66affSColin Finck       MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
1873c2c66affSColin Finck 
1874c2c66affSColin Finck     while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1875c2c66affSColin Finck       MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
1876c2c66affSColin Finck 
1877c2c66affSColin Finck cleanup:
1878c2c66affSColin Finck 
1879c2c66affSColin Finck     return( ret );
1880c2c66affSColin Finck }
1881c2c66affSColin Finck 
1882c2c66affSColin Finck /*
1883c2c66affSColin Finck  * Modulo: r = A mod b
1884c2c66affSColin Finck  */
1885c2c66affSColin Finck int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1886c2c66affSColin Finck {
1887c2c66affSColin Finck     size_t i;
1888c2c66affSColin Finck     mbedtls_mpi_uint x, y, z;
1889*cbda039fSThomas Faber     MPI_VALIDATE_RET( r != NULL );
1890*cbda039fSThomas Faber     MPI_VALIDATE_RET( A != NULL );
1891c2c66affSColin Finck 
1892c2c66affSColin Finck     if( b == 0 )
1893c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
1894c2c66affSColin Finck 
1895c2c66affSColin Finck     if( b < 0 )
1896c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
1897c2c66affSColin Finck 
1898c2c66affSColin Finck     /*
1899c2c66affSColin Finck      * handle trivial cases
1900c2c66affSColin Finck      */
1901c2c66affSColin Finck     if( b == 1 )
1902c2c66affSColin Finck     {
1903c2c66affSColin Finck         *r = 0;
1904c2c66affSColin Finck         return( 0 );
1905c2c66affSColin Finck     }
1906c2c66affSColin Finck 
1907c2c66affSColin Finck     if( b == 2 )
1908c2c66affSColin Finck     {
1909c2c66affSColin Finck         *r = A->p[0] & 1;
1910c2c66affSColin Finck         return( 0 );
1911c2c66affSColin Finck     }
1912c2c66affSColin Finck 
1913c2c66affSColin Finck     /*
1914c2c66affSColin Finck      * general case
1915c2c66affSColin Finck      */
1916c2c66affSColin Finck     for( i = A->n, y = 0; i > 0; i-- )
1917c2c66affSColin Finck     {
1918c2c66affSColin Finck         x  = A->p[i - 1];
1919c2c66affSColin Finck         y  = ( y << biH ) | ( x >> biH );
1920c2c66affSColin Finck         z  = y / b;
1921c2c66affSColin Finck         y -= z * b;
1922c2c66affSColin Finck 
1923c2c66affSColin Finck         x <<= biH;
1924c2c66affSColin Finck         y  = ( y << biH ) | ( x >> biH );
1925c2c66affSColin Finck         z  = y / b;
1926c2c66affSColin Finck         y -= z * b;
1927c2c66affSColin Finck     }
1928c2c66affSColin Finck 
1929c2c66affSColin Finck     /*
1930c2c66affSColin Finck      * If A is negative, then the current y represents a negative value.
1931c2c66affSColin Finck      * Flipping it to the positive side.
1932c2c66affSColin Finck      */
1933c2c66affSColin Finck     if( A->s < 0 && y != 0 )
1934c2c66affSColin Finck         y = b - y;
1935c2c66affSColin Finck 
1936c2c66affSColin Finck     *r = y;
1937c2c66affSColin Finck 
1938c2c66affSColin Finck     return( 0 );
1939c2c66affSColin Finck }
1940c2c66affSColin Finck 
1941c2c66affSColin Finck /*
1942c2c66affSColin Finck  * Fast Montgomery initialization (thanks to Tom St Denis)
1943c2c66affSColin Finck  */
1944c2c66affSColin Finck static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
1945c2c66affSColin Finck {
1946c2c66affSColin Finck     mbedtls_mpi_uint x, m0 = N->p[0];
1947c2c66affSColin Finck     unsigned int i;
1948c2c66affSColin Finck 
1949c2c66affSColin Finck     x  = m0;
1950c2c66affSColin Finck     x += ( ( m0 + 2 ) & 4 ) << 1;
1951c2c66affSColin Finck 
1952c2c66affSColin Finck     for( i = biL; i >= 8; i /= 2 )
1953c2c66affSColin Finck         x *= ( 2 - ( m0 * x ) );
1954c2c66affSColin Finck 
1955c2c66affSColin Finck     *mm = ~x + 1;
1956c2c66affSColin Finck }
1957c2c66affSColin Finck 
1958292f67afSThomas Faber /** Montgomery multiplication: A = A * B * R^-1 mod N  (HAC 14.36)
1959292f67afSThomas Faber  *
1960292f67afSThomas Faber  * \param[in,out]   A   One of the numbers to multiply.
1961292f67afSThomas Faber  *                      It must have at least as many limbs as N
1962292f67afSThomas Faber  *                      (A->n >= N->n), and any limbs beyond n are ignored.
1963292f67afSThomas Faber  *                      On successful completion, A contains the result of
1964292f67afSThomas Faber  *                      the multiplication A * B * R^-1 mod N where
1965292f67afSThomas Faber  *                      R = (2^ciL)^n.
1966292f67afSThomas Faber  * \param[in]       B   One of the numbers to multiply.
1967292f67afSThomas Faber  *                      It must be nonzero and must not have more limbs than N
1968292f67afSThomas Faber  *                      (B->n <= N->n).
1969292f67afSThomas Faber  * \param[in]       N   The modulo. N must be odd.
1970292f67afSThomas Faber  * \param           mm  The value calculated by `mpi_montg_init(&mm, N)`.
1971292f67afSThomas Faber  *                      This is -N^-1 mod 2^ciL.
1972292f67afSThomas Faber  * \param[in,out]   T   A bignum for temporary storage.
1973292f67afSThomas Faber  *                      It must be at least twice the limb size of N plus 2
1974292f67afSThomas Faber  *                      (T->n >= 2 * (N->n + 1)).
1975292f67afSThomas Faber  *                      Its initial content is unused and
1976292f67afSThomas Faber  *                      its final content is indeterminate.
1977292f67afSThomas Faber  *                      Note that unlike the usual convention in the library
1978292f67afSThomas Faber  *                      for `const mbedtls_mpi*`, the content of T can change.
1979c2c66affSColin Finck  */
1980292f67afSThomas Faber static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1981c2c66affSColin Finck                          const mbedtls_mpi *T )
1982c2c66affSColin Finck {
1983c2c66affSColin Finck     size_t i, n, m;
1984c2c66affSColin Finck     mbedtls_mpi_uint u0, u1, *d;
1985c2c66affSColin Finck 
1986c2c66affSColin Finck     memset( T->p, 0, T->n * ciL );
1987c2c66affSColin Finck 
1988c2c66affSColin Finck     d = T->p;
1989c2c66affSColin Finck     n = N->n;
1990c2c66affSColin Finck     m = ( B->n < n ) ? B->n : n;
1991c2c66affSColin Finck 
1992c2c66affSColin Finck     for( i = 0; i < n; i++ )
1993c2c66affSColin Finck     {
1994c2c66affSColin Finck         /*
1995c2c66affSColin Finck          * T = (T + u0*B + u1*N) / 2^biL
1996c2c66affSColin Finck          */
1997c2c66affSColin Finck         u0 = A->p[i];
1998c2c66affSColin Finck         u1 = ( d[0] + u0 * B->p[0] ) * mm;
1999c2c66affSColin Finck 
2000c2c66affSColin Finck         mpi_mul_hlp( m, B->p, d, u0 );
2001c2c66affSColin Finck         mpi_mul_hlp( n, N->p, d, u1 );
2002c2c66affSColin Finck 
2003c2c66affSColin Finck         *d++ = u0; d[n + 1] = 0;
2004c2c66affSColin Finck     }
2005c2c66affSColin Finck 
2006292f67afSThomas Faber     /* At this point, d is either the desired result or the desired result
2007292f67afSThomas Faber      * plus N. We now potentially subtract N, avoiding leaking whether the
2008292f67afSThomas Faber      * subtraction is performed through side channels. */
2009c2c66affSColin Finck 
2010292f67afSThomas Faber     /* Copy the n least significant limbs of d to A, so that
2011292f67afSThomas Faber      * A = d if d < N (recall that N has n limbs). */
2012292f67afSThomas Faber     memcpy( A->p, d, n * ciL );
2013292f67afSThomas Faber     /* If d >= N then we want to set A to d - N. To prevent timing attacks,
2014292f67afSThomas Faber      * do the calculation without using conditional tests. */
2015292f67afSThomas Faber     /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
2016292f67afSThomas Faber     d[n] += 1;
2017292f67afSThomas Faber     d[n] -= mpi_sub_hlp( n, d, N->p );
2018292f67afSThomas Faber     /* If d0 < N then d < (2^biL)^n
2019292f67afSThomas Faber      * so d[n] == 0 and we want to keep A as it is.
2020292f67afSThomas Faber      * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2021292f67afSThomas Faber      * so d[n] == 1 and we want to set A to the result of the subtraction
2022292f67afSThomas Faber      * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2023292f67afSThomas Faber      * This exactly corresponds to a conditional assignment. */
2024292f67afSThomas Faber     mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
2025c2c66affSColin Finck }
2026c2c66affSColin Finck 
2027c2c66affSColin Finck /*
2028c2c66affSColin Finck  * Montgomery reduction: A = A * R^-1 mod N
2029292f67afSThomas Faber  *
2030292f67afSThomas Faber  * See mpi_montmul() regarding constraints and guarantees on the parameters.
2031c2c66affSColin Finck  */
2032*cbda039fSThomas Faber static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
2033*cbda039fSThomas Faber                          mbedtls_mpi_uint mm, const mbedtls_mpi *T )
2034c2c66affSColin Finck {
2035c2c66affSColin Finck     mbedtls_mpi_uint z = 1;
2036c2c66affSColin Finck     mbedtls_mpi U;
2037c2c66affSColin Finck 
2038c2c66affSColin Finck     U.n = U.s = (int) z;
2039c2c66affSColin Finck     U.p = &z;
2040c2c66affSColin Finck 
2041292f67afSThomas Faber     mpi_montmul( A, &U, N, mm, T );
2042c2c66affSColin Finck }
2043c2c66affSColin Finck 
2044c2c66affSColin Finck /*
2045c2c66affSColin Finck  * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
2046c2c66affSColin Finck  */
2047*cbda039fSThomas Faber int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2048*cbda039fSThomas Faber                          const mbedtls_mpi *E, const mbedtls_mpi *N,
2049*cbda039fSThomas Faber                          mbedtls_mpi *_RR )
2050c2c66affSColin Finck {
2051c2c66affSColin Finck     int ret;
2052c2c66affSColin Finck     size_t wbits, wsize, one = 1;
2053c2c66affSColin Finck     size_t i, j, nblimbs;
2054c2c66affSColin Finck     size_t bufsize, nbits;
2055c2c66affSColin Finck     mbedtls_mpi_uint ei, mm, state;
20562e53fc8eSThomas Faber     mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
2057c2c66affSColin Finck     int neg;
2058c2c66affSColin Finck 
2059*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
2060*cbda039fSThomas Faber     MPI_VALIDATE_RET( A != NULL );
2061*cbda039fSThomas Faber     MPI_VALIDATE_RET( E != NULL );
2062*cbda039fSThomas Faber     MPI_VALIDATE_RET( N != NULL );
2063*cbda039fSThomas Faber 
2064d9e6c9b5SThomas Faber     if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
2065c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2066c2c66affSColin Finck 
2067c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2068c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2069c2c66affSColin Finck 
20702e53fc8eSThomas Faber     if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
20712e53fc8eSThomas Faber         mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
20722e53fc8eSThomas Faber         return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
20732e53fc8eSThomas Faber 
2074c2c66affSColin Finck     /*
2075c2c66affSColin Finck      * Init temps and window size
2076c2c66affSColin Finck      */
2077c2c66affSColin Finck     mpi_montg_init( &mm, N );
2078c2c66affSColin Finck     mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2079c2c66affSColin Finck     mbedtls_mpi_init( &Apos );
2080c2c66affSColin Finck     memset( W, 0, sizeof( W ) );
2081c2c66affSColin Finck 
2082c2c66affSColin Finck     i = mbedtls_mpi_bitlen( E );
2083c2c66affSColin Finck 
2084c2c66affSColin Finck     wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2085c2c66affSColin Finck             ( i >  79 ) ? 4 : ( i >  23 ) ? 3 : 1;
2086c2c66affSColin Finck 
2087430656f0SThomas Faber #if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
2088c2c66affSColin Finck     if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2089c2c66affSColin Finck         wsize = MBEDTLS_MPI_WINDOW_SIZE;
2090430656f0SThomas Faber #endif
2091c2c66affSColin Finck 
2092c2c66affSColin Finck     j = N->n + 1;
2093c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2094c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1],  j ) );
2095c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
2096c2c66affSColin Finck 
2097c2c66affSColin Finck     /*
2098c2c66affSColin Finck      * Compensate for negative A (and correct at the end)
2099c2c66affSColin Finck      */
2100c2c66affSColin Finck     neg = ( A->s == -1 );
2101c2c66affSColin Finck     if( neg )
2102c2c66affSColin Finck     {
2103c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
2104c2c66affSColin Finck         Apos.s = 1;
2105c2c66affSColin Finck         A = &Apos;
2106c2c66affSColin Finck     }
2107c2c66affSColin Finck 
2108c2c66affSColin Finck     /*
2109c2c66affSColin Finck      * If 1st call, pre-compute R^2 mod N
2110c2c66affSColin Finck      */
2111c2c66affSColin Finck     if( _RR == NULL || _RR->p == NULL )
2112c2c66affSColin Finck     {
2113c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2114c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2115c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
2116c2c66affSColin Finck 
2117c2c66affSColin Finck         if( _RR != NULL )
2118c2c66affSColin Finck             memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
2119c2c66affSColin Finck     }
2120c2c66affSColin Finck     else
2121c2c66affSColin Finck         memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
2122c2c66affSColin Finck 
2123c2c66affSColin Finck     /*
2124c2c66affSColin Finck      * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2125c2c66affSColin Finck      */
2126c2c66affSColin Finck     if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2127c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
2128c2c66affSColin Finck     else
2129c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
2130c2c66affSColin Finck 
2131292f67afSThomas Faber     mpi_montmul( &W[1], &RR, N, mm, &T );
2132c2c66affSColin Finck 
2133c2c66affSColin Finck     /*
2134c2c66affSColin Finck      * X = R^2 * R^-1 mod N = R mod N
2135c2c66affSColin Finck      */
2136c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
2137292f67afSThomas Faber     mpi_montred( X, N, mm, &T );
2138c2c66affSColin Finck 
2139c2c66affSColin Finck     if( wsize > 1 )
2140c2c66affSColin Finck     {
2141c2c66affSColin Finck         /*
2142c2c66affSColin Finck          * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2143c2c66affSColin Finck          */
2144c2c66affSColin Finck         j =  one << ( wsize - 1 );
2145c2c66affSColin Finck 
2146c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2147c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1]    ) );
2148c2c66affSColin Finck 
2149c2c66affSColin Finck         for( i = 0; i < wsize - 1; i++ )
2150292f67afSThomas Faber             mpi_montmul( &W[j], &W[j], N, mm, &T );
2151c2c66affSColin Finck 
2152c2c66affSColin Finck         /*
2153c2c66affSColin Finck          * W[i] = W[i - 1] * W[1]
2154c2c66affSColin Finck          */
2155c2c66affSColin Finck         for( i = j + 1; i < ( one << wsize ); i++ )
2156c2c66affSColin Finck         {
2157c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2158c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
2159c2c66affSColin Finck 
2160292f67afSThomas Faber             mpi_montmul( &W[i], &W[1], N, mm, &T );
2161c2c66affSColin Finck         }
2162c2c66affSColin Finck     }
2163c2c66affSColin Finck 
2164c2c66affSColin Finck     nblimbs = E->n;
2165c2c66affSColin Finck     bufsize = 0;
2166c2c66affSColin Finck     nbits   = 0;
2167c2c66affSColin Finck     wbits   = 0;
2168c2c66affSColin Finck     state   = 0;
2169c2c66affSColin Finck 
2170c2c66affSColin Finck     while( 1 )
2171c2c66affSColin Finck     {
2172c2c66affSColin Finck         if( bufsize == 0 )
2173c2c66affSColin Finck         {
2174c2c66affSColin Finck             if( nblimbs == 0 )
2175c2c66affSColin Finck                 break;
2176c2c66affSColin Finck 
2177c2c66affSColin Finck             nblimbs--;
2178c2c66affSColin Finck 
2179c2c66affSColin Finck             bufsize = sizeof( mbedtls_mpi_uint ) << 3;
2180c2c66affSColin Finck         }
2181c2c66affSColin Finck 
2182c2c66affSColin Finck         bufsize--;
2183c2c66affSColin Finck 
2184c2c66affSColin Finck         ei = (E->p[nblimbs] >> bufsize) & 1;
2185c2c66affSColin Finck 
2186c2c66affSColin Finck         /*
2187c2c66affSColin Finck          * skip leading 0s
2188c2c66affSColin Finck          */
2189c2c66affSColin Finck         if( ei == 0 && state == 0 )
2190c2c66affSColin Finck             continue;
2191c2c66affSColin Finck 
2192c2c66affSColin Finck         if( ei == 0 && state == 1 )
2193c2c66affSColin Finck         {
2194c2c66affSColin Finck             /*
2195c2c66affSColin Finck              * out of window, square X
2196c2c66affSColin Finck              */
2197292f67afSThomas Faber             mpi_montmul( X, X, N, mm, &T );
2198c2c66affSColin Finck             continue;
2199c2c66affSColin Finck         }
2200c2c66affSColin Finck 
2201c2c66affSColin Finck         /*
2202c2c66affSColin Finck          * add ei to current window
2203c2c66affSColin Finck          */
2204c2c66affSColin Finck         state = 2;
2205c2c66affSColin Finck 
2206c2c66affSColin Finck         nbits++;
2207c2c66affSColin Finck         wbits |= ( ei << ( wsize - nbits ) );
2208c2c66affSColin Finck 
2209c2c66affSColin Finck         if( nbits == wsize )
2210c2c66affSColin Finck         {
2211c2c66affSColin Finck             /*
2212c2c66affSColin Finck              * X = X^wsize R^-1 mod N
2213c2c66affSColin Finck              */
2214c2c66affSColin Finck             for( i = 0; i < wsize; i++ )
2215292f67afSThomas Faber                 mpi_montmul( X, X, N, mm, &T );
2216c2c66affSColin Finck 
2217c2c66affSColin Finck             /*
2218c2c66affSColin Finck              * X = X * W[wbits] R^-1 mod N
2219c2c66affSColin Finck              */
2220292f67afSThomas Faber             mpi_montmul( X, &W[wbits], N, mm, &T );
2221c2c66affSColin Finck 
2222c2c66affSColin Finck             state--;
2223c2c66affSColin Finck             nbits = 0;
2224c2c66affSColin Finck             wbits = 0;
2225c2c66affSColin Finck         }
2226c2c66affSColin Finck     }
2227c2c66affSColin Finck 
2228c2c66affSColin Finck     /*
2229c2c66affSColin Finck      * process the remaining bits
2230c2c66affSColin Finck      */
2231c2c66affSColin Finck     for( i = 0; i < nbits; i++ )
2232c2c66affSColin Finck     {
2233292f67afSThomas Faber         mpi_montmul( X, X, N, mm, &T );
2234c2c66affSColin Finck 
2235c2c66affSColin Finck         wbits <<= 1;
2236c2c66affSColin Finck 
2237c2c66affSColin Finck         if( ( wbits & ( one << wsize ) ) != 0 )
2238292f67afSThomas Faber             mpi_montmul( X, &W[1], N, mm, &T );
2239c2c66affSColin Finck     }
2240c2c66affSColin Finck 
2241c2c66affSColin Finck     /*
2242c2c66affSColin Finck      * X = A^E * R * R^-1 mod N = A^E mod N
2243c2c66affSColin Finck      */
2244292f67afSThomas Faber     mpi_montred( X, N, mm, &T );
2245c2c66affSColin Finck 
2246c2c66affSColin Finck     if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
2247c2c66affSColin Finck     {
2248c2c66affSColin Finck         X->s = -1;
2249c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
2250c2c66affSColin Finck     }
2251c2c66affSColin Finck 
2252c2c66affSColin Finck cleanup:
2253c2c66affSColin Finck 
2254c2c66affSColin Finck     for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
2255c2c66affSColin Finck         mbedtls_mpi_free( &W[i] );
2256c2c66affSColin Finck 
2257c2c66affSColin Finck     mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
2258c2c66affSColin Finck 
2259c2c66affSColin Finck     if( _RR == NULL || _RR->p == NULL )
2260c2c66affSColin Finck         mbedtls_mpi_free( &RR );
2261c2c66affSColin Finck 
2262c2c66affSColin Finck     return( ret );
2263c2c66affSColin Finck }
2264c2c66affSColin Finck 
2265c2c66affSColin Finck /*
2266c2c66affSColin Finck  * Greatest common divisor: G = gcd(A, B)  (HAC 14.54)
2267c2c66affSColin Finck  */
2268c2c66affSColin Finck int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
2269c2c66affSColin Finck {
2270c2c66affSColin Finck     int ret;
2271c2c66affSColin Finck     size_t lz, lzt;
2272c2c66affSColin Finck     mbedtls_mpi TG, TA, TB;
2273c2c66affSColin Finck 
2274*cbda039fSThomas Faber     MPI_VALIDATE_RET( G != NULL );
2275*cbda039fSThomas Faber     MPI_VALIDATE_RET( A != NULL );
2276*cbda039fSThomas Faber     MPI_VALIDATE_RET( B != NULL );
2277*cbda039fSThomas Faber 
2278c2c66affSColin Finck     mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
2279c2c66affSColin Finck 
2280c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2281c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
2282c2c66affSColin Finck 
2283c2c66affSColin Finck     lz = mbedtls_mpi_lsb( &TA );
2284c2c66affSColin Finck     lzt = mbedtls_mpi_lsb( &TB );
2285c2c66affSColin Finck 
2286c2c66affSColin Finck     if( lzt < lz )
2287c2c66affSColin Finck         lz = lzt;
2288c2c66affSColin Finck 
2289c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2290c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
2291c2c66affSColin Finck 
2292c2c66affSColin Finck     TA.s = TB.s = 1;
2293c2c66affSColin Finck 
2294c2c66affSColin Finck     while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
2295c2c66affSColin Finck     {
2296c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2297c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
2298c2c66affSColin Finck 
2299c2c66affSColin Finck         if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
2300c2c66affSColin Finck         {
2301c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2302c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
2303c2c66affSColin Finck         }
2304c2c66affSColin Finck         else
2305c2c66affSColin Finck         {
2306c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2307c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
2308c2c66affSColin Finck         }
2309c2c66affSColin Finck     }
2310c2c66affSColin Finck 
2311c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2312c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
2313c2c66affSColin Finck 
2314c2c66affSColin Finck cleanup:
2315c2c66affSColin Finck 
2316c2c66affSColin Finck     mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
2317c2c66affSColin Finck 
2318c2c66affSColin Finck     return( ret );
2319c2c66affSColin Finck }
2320c2c66affSColin Finck 
2321c2c66affSColin Finck /*
2322c2c66affSColin Finck  * Fill X with size bytes of random.
2323c2c66affSColin Finck  *
2324c2c66affSColin Finck  * Use a temporary bytes representation to make sure the result is the same
2325c2c66affSColin Finck  * regardless of the platform endianness (useful when f_rng is actually
2326c2c66affSColin Finck  * deterministic, eg for tests).
2327c2c66affSColin Finck  */
2328c2c66affSColin Finck int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
2329c2c66affSColin Finck                      int (*f_rng)(void *, unsigned char *, size_t),
2330c2c66affSColin Finck                      void *p_rng )
2331c2c66affSColin Finck {
2332c2c66affSColin Finck     int ret;
2333*cbda039fSThomas Faber     size_t const limbs = CHARS_TO_LIMBS( size );
2334*cbda039fSThomas Faber     size_t const overhead = ( limbs * ciL ) - size;
2335*cbda039fSThomas Faber     unsigned char *Xp;
2336c2c66affSColin Finck 
2337*cbda039fSThomas Faber     MPI_VALIDATE_RET( X     != NULL );
2338*cbda039fSThomas Faber     MPI_VALIDATE_RET( f_rng != NULL );
2339c2c66affSColin Finck 
2340*cbda039fSThomas Faber     /* Ensure that target MPI has exactly the necessary number of limbs */
2341*cbda039fSThomas Faber     if( X->n != limbs )
2342*cbda039fSThomas Faber     {
2343*cbda039fSThomas Faber         mbedtls_mpi_free( X );
2344*cbda039fSThomas Faber         mbedtls_mpi_init( X );
2345*cbda039fSThomas Faber         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2346*cbda039fSThomas Faber     }
2347*cbda039fSThomas Faber     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
2348*cbda039fSThomas Faber 
2349*cbda039fSThomas Faber     Xp = (unsigned char*) X->p;
2350*cbda039fSThomas Faber     MBEDTLS_MPI_CHK( f_rng( p_rng, Xp + overhead, size ) );
2351*cbda039fSThomas Faber 
2352*cbda039fSThomas Faber     mpi_bigendian_to_host( X->p, limbs );
2353c2c66affSColin Finck 
2354c2c66affSColin Finck cleanup:
2355c2c66affSColin Finck     return( ret );
2356c2c66affSColin Finck }
2357c2c66affSColin Finck 
2358c2c66affSColin Finck /*
2359c2c66affSColin Finck  * Modular inverse: X = A^-1 mod N  (HAC 14.61 / 14.64)
2360c2c66affSColin Finck  */
2361c2c66affSColin Finck int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
2362c2c66affSColin Finck {
2363c2c66affSColin Finck     int ret;
2364c2c66affSColin Finck     mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
2365*cbda039fSThomas Faber     MPI_VALIDATE_RET( X != NULL );
2366*cbda039fSThomas Faber     MPI_VALIDATE_RET( A != NULL );
2367*cbda039fSThomas Faber     MPI_VALIDATE_RET( N != NULL );
2368c2c66affSColin Finck 
2369c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
2370c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2371c2c66affSColin Finck 
2372c2c66affSColin Finck     mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2373c2c66affSColin Finck     mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2374c2c66affSColin Finck     mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
2375c2c66affSColin Finck 
2376c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
2377c2c66affSColin Finck 
2378c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
2379c2c66affSColin Finck     {
2380c2c66affSColin Finck         ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2381c2c66affSColin Finck         goto cleanup;
2382c2c66affSColin Finck     }
2383c2c66affSColin Finck 
2384c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2385c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2386c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2387c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
2388c2c66affSColin Finck 
2389c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2390c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2391c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2392c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
2393c2c66affSColin Finck 
2394c2c66affSColin Finck     do
2395c2c66affSColin Finck     {
2396c2c66affSColin Finck         while( ( TU.p[0] & 1 ) == 0 )
2397c2c66affSColin Finck         {
2398c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
2399c2c66affSColin Finck 
2400c2c66affSColin Finck             if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2401c2c66affSColin Finck             {
2402c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2403c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
2404c2c66affSColin Finck             }
2405c2c66affSColin Finck 
2406c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2407c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
2408c2c66affSColin Finck         }
2409c2c66affSColin Finck 
2410c2c66affSColin Finck         while( ( TV.p[0] & 1 ) == 0 )
2411c2c66affSColin Finck         {
2412c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
2413c2c66affSColin Finck 
2414c2c66affSColin Finck             if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2415c2c66affSColin Finck             {
2416c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2417c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
2418c2c66affSColin Finck             }
2419c2c66affSColin Finck 
2420c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2421c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
2422c2c66affSColin Finck         }
2423c2c66affSColin Finck 
2424c2c66affSColin Finck         if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
2425c2c66affSColin Finck         {
2426c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2427c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2428c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
2429c2c66affSColin Finck         }
2430c2c66affSColin Finck         else
2431c2c66affSColin Finck         {
2432c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2433c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2434c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
2435c2c66affSColin Finck         }
2436c2c66affSColin Finck     }
2437c2c66affSColin Finck     while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
2438c2c66affSColin Finck 
2439c2c66affSColin Finck     while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2440c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
2441c2c66affSColin Finck 
2442c2c66affSColin Finck     while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2443c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
2444c2c66affSColin Finck 
2445c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
2446c2c66affSColin Finck 
2447c2c66affSColin Finck cleanup:
2448c2c66affSColin Finck 
2449c2c66affSColin Finck     mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2450c2c66affSColin Finck     mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2451c2c66affSColin Finck     mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
2452c2c66affSColin Finck 
2453c2c66affSColin Finck     return( ret );
2454c2c66affSColin Finck }
2455c2c66affSColin Finck 
2456c2c66affSColin Finck #if defined(MBEDTLS_GENPRIME)
2457c2c66affSColin Finck 
2458c2c66affSColin Finck static const int small_prime[] =
2459c2c66affSColin Finck {
2460c2c66affSColin Finck         3,    5,    7,   11,   13,   17,   19,   23,
2461c2c66affSColin Finck        29,   31,   37,   41,   43,   47,   53,   59,
2462c2c66affSColin Finck        61,   67,   71,   73,   79,   83,   89,   97,
2463c2c66affSColin Finck       101,  103,  107,  109,  113,  127,  131,  137,
2464c2c66affSColin Finck       139,  149,  151,  157,  163,  167,  173,  179,
2465c2c66affSColin Finck       181,  191,  193,  197,  199,  211,  223,  227,
2466c2c66affSColin Finck       229,  233,  239,  241,  251,  257,  263,  269,
2467c2c66affSColin Finck       271,  277,  281,  283,  293,  307,  311,  313,
2468c2c66affSColin Finck       317,  331,  337,  347,  349,  353,  359,  367,
2469c2c66affSColin Finck       373,  379,  383,  389,  397,  401,  409,  419,
2470c2c66affSColin Finck       421,  431,  433,  439,  443,  449,  457,  461,
2471c2c66affSColin Finck       463,  467,  479,  487,  491,  499,  503,  509,
2472c2c66affSColin Finck       521,  523,  541,  547,  557,  563,  569,  571,
2473c2c66affSColin Finck       577,  587,  593,  599,  601,  607,  613,  617,
2474c2c66affSColin Finck       619,  631,  641,  643,  647,  653,  659,  661,
2475c2c66affSColin Finck       673,  677,  683,  691,  701,  709,  719,  727,
2476c2c66affSColin Finck       733,  739,  743,  751,  757,  761,  769,  773,
2477c2c66affSColin Finck       787,  797,  809,  811,  821,  823,  827,  829,
2478c2c66affSColin Finck       839,  853,  857,  859,  863,  877,  881,  883,
2479c2c66affSColin Finck       887,  907,  911,  919,  929,  937,  941,  947,
2480c2c66affSColin Finck       953,  967,  971,  977,  983,  991,  997, -103
2481c2c66affSColin Finck };
2482c2c66affSColin Finck 
2483c2c66affSColin Finck /*
2484c2c66affSColin Finck  * Small divisors test (X must be positive)
2485c2c66affSColin Finck  *
2486c2c66affSColin Finck  * Return values:
2487c2c66affSColin Finck  * 0: no small factor (possible prime, more tests needed)
2488c2c66affSColin Finck  * 1: certain prime
2489c2c66affSColin Finck  * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2490c2c66affSColin Finck  * other negative: error
2491c2c66affSColin Finck  */
2492c2c66affSColin Finck static int mpi_check_small_factors( const mbedtls_mpi *X )
2493c2c66affSColin Finck {
2494c2c66affSColin Finck     int ret = 0;
2495c2c66affSColin Finck     size_t i;
2496c2c66affSColin Finck     mbedtls_mpi_uint r;
2497c2c66affSColin Finck 
2498c2c66affSColin Finck     if( ( X->p[0] & 1 ) == 0 )
2499c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
2500c2c66affSColin Finck 
2501c2c66affSColin Finck     for( i = 0; small_prime[i] > 0; i++ )
2502c2c66affSColin Finck     {
2503c2c66affSColin Finck         if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
2504c2c66affSColin Finck             return( 1 );
2505c2c66affSColin Finck 
2506c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
2507c2c66affSColin Finck 
2508c2c66affSColin Finck         if( r == 0 )
2509c2c66affSColin Finck             return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
2510c2c66affSColin Finck     }
2511c2c66affSColin Finck 
2512c2c66affSColin Finck cleanup:
2513c2c66affSColin Finck     return( ret );
2514c2c66affSColin Finck }
2515c2c66affSColin Finck 
2516c2c66affSColin Finck /*
2517c2c66affSColin Finck  * Miller-Rabin pseudo-primality test  (HAC 4.24)
2518c2c66affSColin Finck  */
25190ba5bc40SThomas Faber static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
2520c2c66affSColin Finck                              int (*f_rng)(void *, unsigned char *, size_t),
2521c2c66affSColin Finck                              void *p_rng )
2522c2c66affSColin Finck {
2523c2c66affSColin Finck     int ret, count;
25240ba5bc40SThomas Faber     size_t i, j, k, s;
2525c2c66affSColin Finck     mbedtls_mpi W, R, T, A, RR;
2526c2c66affSColin Finck 
2527*cbda039fSThomas Faber     MPI_VALIDATE_RET( X     != NULL );
2528*cbda039fSThomas Faber     MPI_VALIDATE_RET( f_rng != NULL );
2529*cbda039fSThomas Faber 
2530*cbda039fSThomas Faber     mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2531*cbda039fSThomas Faber     mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2532c2c66affSColin Finck     mbedtls_mpi_init( &RR );
2533c2c66affSColin Finck 
2534c2c66affSColin Finck     /*
2535c2c66affSColin Finck      * W = |X| - 1
2536c2c66affSColin Finck      * R = W >> lsb( W )
2537c2c66affSColin Finck      */
2538c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2539c2c66affSColin Finck     s = mbedtls_mpi_lsb( &W );
2540c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2541c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
2542c2c66affSColin Finck 
25430ba5bc40SThomas Faber     for( i = 0; i < rounds; i++ )
2544c2c66affSColin Finck     {
2545c2c66affSColin Finck         /*
2546c2c66affSColin Finck          * pick a random A, 1 < A < |X| - 1
2547c2c66affSColin Finck          */
2548c2c66affSColin Finck         count = 0;
2549c2c66affSColin Finck         do {
2550c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
2551c2c66affSColin Finck 
2552c2c66affSColin Finck             j = mbedtls_mpi_bitlen( &A );
2553c2c66affSColin Finck             k = mbedtls_mpi_bitlen( &W );
2554c2c66affSColin Finck             if (j > k) {
25550ba5bc40SThomas Faber                 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
2556c2c66affSColin Finck             }
2557c2c66affSColin Finck 
2558c2c66affSColin Finck             if (count++ > 30) {
2559c1eccaffSThomas Faber                 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2560c1eccaffSThomas Faber                 goto cleanup;
2561c2c66affSColin Finck             }
2562c2c66affSColin Finck 
2563c2c66affSColin Finck         } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2564c2c66affSColin Finck                   mbedtls_mpi_cmp_int( &A, 1 )  <= 0    );
2565c2c66affSColin Finck 
2566c2c66affSColin Finck         /*
2567c2c66affSColin Finck          * A = A^R mod |X|
2568c2c66affSColin Finck          */
2569c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
2570c2c66affSColin Finck 
2571c2c66affSColin Finck         if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2572c2c66affSColin Finck             mbedtls_mpi_cmp_int( &A,  1 ) == 0 )
2573c2c66affSColin Finck             continue;
2574c2c66affSColin Finck 
2575c2c66affSColin Finck         j = 1;
2576c2c66affSColin Finck         while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
2577c2c66affSColin Finck         {
2578c2c66affSColin Finck             /*
2579c2c66affSColin Finck              * A = A * A mod |X|
2580c2c66affSColin Finck              */
2581c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2582c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X  ) );
2583c2c66affSColin Finck 
2584c2c66affSColin Finck             if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
2585c2c66affSColin Finck                 break;
2586c2c66affSColin Finck 
2587c2c66affSColin Finck             j++;
2588c2c66affSColin Finck         }
2589c2c66affSColin Finck 
2590c2c66affSColin Finck         /*
2591c2c66affSColin Finck          * not prime if A != |X| - 1 or A == 1
2592c2c66affSColin Finck          */
2593c2c66affSColin Finck         if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2594c2c66affSColin Finck             mbedtls_mpi_cmp_int( &A,  1 ) == 0 )
2595c2c66affSColin Finck         {
2596c2c66affSColin Finck             ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2597c2c66affSColin Finck             break;
2598c2c66affSColin Finck         }
2599c2c66affSColin Finck     }
2600c2c66affSColin Finck 
2601c2c66affSColin Finck cleanup:
2602*cbda039fSThomas Faber     mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2603*cbda039fSThomas Faber     mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2604c2c66affSColin Finck     mbedtls_mpi_free( &RR );
2605c2c66affSColin Finck 
2606c2c66affSColin Finck     return( ret );
2607c2c66affSColin Finck }
2608c2c66affSColin Finck 
2609c2c66affSColin Finck /*
2610c2c66affSColin Finck  * Pseudo-primality test: small factors, then Miller-Rabin
2611c2c66affSColin Finck  */
2612*cbda039fSThomas Faber int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2613c2c66affSColin Finck                               int (*f_rng)(void *, unsigned char *, size_t),
2614c2c66affSColin Finck                               void *p_rng )
2615c2c66affSColin Finck {
2616c2c66affSColin Finck     int ret;
2617c2c66affSColin Finck     mbedtls_mpi XX;
2618*cbda039fSThomas Faber     MPI_VALIDATE_RET( X     != NULL );
2619*cbda039fSThomas Faber     MPI_VALIDATE_RET( f_rng != NULL );
2620c2c66affSColin Finck 
2621c2c66affSColin Finck     XX.s = 1;
2622c2c66affSColin Finck     XX.n = X->n;
2623c2c66affSColin Finck     XX.p = X->p;
2624c2c66affSColin Finck 
2625c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2626c2c66affSColin Finck         mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2627c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
2628c2c66affSColin Finck 
2629c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
2630c2c66affSColin Finck         return( 0 );
2631c2c66affSColin Finck 
2632c2c66affSColin Finck     if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2633c2c66affSColin Finck     {
2634c2c66affSColin Finck         if( ret == 1 )
2635c2c66affSColin Finck             return( 0 );
2636c2c66affSColin Finck 
2637c2c66affSColin Finck         return( ret );
2638c2c66affSColin Finck     }
2639c2c66affSColin Finck 
26400ba5bc40SThomas Faber     return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
26410ba5bc40SThomas Faber }
26420ba5bc40SThomas Faber 
2643*cbda039fSThomas Faber #if !defined(MBEDTLS_DEPRECATED_REMOVED)
26440ba5bc40SThomas Faber /*
26450ba5bc40SThomas Faber  * Pseudo-primality test, error probability 2^-80
26460ba5bc40SThomas Faber  */
26470ba5bc40SThomas Faber int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
26480ba5bc40SThomas Faber                   int (*f_rng)(void *, unsigned char *, size_t),
26490ba5bc40SThomas Faber                   void *p_rng )
26500ba5bc40SThomas Faber {
2651*cbda039fSThomas Faber     MPI_VALIDATE_RET( X     != NULL );
2652*cbda039fSThomas Faber     MPI_VALIDATE_RET( f_rng != NULL );
2653*cbda039fSThomas Faber 
2654*cbda039fSThomas Faber     /*
2655*cbda039fSThomas Faber      * In the past our key generation aimed for an error rate of at most
2656*cbda039fSThomas Faber      * 2^-80. Since this function is deprecated, aim for the same certainty
2657*cbda039fSThomas Faber      * here as well.
2658*cbda039fSThomas Faber      */
2659*cbda039fSThomas Faber     return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
2660c2c66affSColin Finck }
2661*cbda039fSThomas Faber #endif
2662c2c66affSColin Finck 
2663c2c66affSColin Finck /*
2664c2c66affSColin Finck  * Prime number generation
2665*cbda039fSThomas Faber  *
2666*cbda039fSThomas Faber  * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2667*cbda039fSThomas Faber  * be either 1024 bits or 1536 bits long, and flags must contain
2668*cbda039fSThomas Faber  * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
2669c2c66affSColin Finck  */
2670*cbda039fSThomas Faber int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
2671c2c66affSColin Finck                    int (*f_rng)(void *, unsigned char *, size_t),
2672c2c66affSColin Finck                    void *p_rng )
2673c2c66affSColin Finck {
2674*cbda039fSThomas Faber #ifdef MBEDTLS_HAVE_INT64
2675*cbda039fSThomas Faber // ceil(2^63.5)
2676*cbda039fSThomas Faber #define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2677*cbda039fSThomas Faber #else
2678*cbda039fSThomas Faber // ceil(2^31.5)
2679*cbda039fSThomas Faber #define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2680*cbda039fSThomas Faber #endif
2681*cbda039fSThomas Faber     int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2682c2c66affSColin Finck     size_t k, n;
26830ba5bc40SThomas Faber     int rounds;
2684c2c66affSColin Finck     mbedtls_mpi_uint r;
2685c2c66affSColin Finck     mbedtls_mpi Y;
2686c2c66affSColin Finck 
2687*cbda039fSThomas Faber     MPI_VALIDATE_RET( X     != NULL );
2688*cbda039fSThomas Faber     MPI_VALIDATE_RET( f_rng != NULL );
2689*cbda039fSThomas Faber 
2690c2c66affSColin Finck     if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2691c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2692c2c66affSColin Finck 
2693c2c66affSColin Finck     mbedtls_mpi_init( &Y );
2694c2c66affSColin Finck 
2695c2c66affSColin Finck     n = BITS_TO_LIMBS( nbits );
2696c2c66affSColin Finck 
2697*cbda039fSThomas Faber     if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2698*cbda039fSThomas Faber     {
26990ba5bc40SThomas Faber         /*
27000ba5bc40SThomas Faber          * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
27010ba5bc40SThomas Faber          */
27020ba5bc40SThomas Faber         rounds = ( ( nbits >= 1300 ) ?  2 : ( nbits >=  850 ) ?  3 :
27030ba5bc40SThomas Faber                    ( nbits >=  650 ) ?  4 : ( nbits >=  350 ) ?  8 :
27040ba5bc40SThomas Faber                    ( nbits >=  250 ) ? 12 : ( nbits >=  150 ) ? 18 : 27 );
2705*cbda039fSThomas Faber     }
2706*cbda039fSThomas Faber     else
2707*cbda039fSThomas Faber     {
2708*cbda039fSThomas Faber         /*
2709*cbda039fSThomas Faber          * 2^-100 error probability, number of rounds computed based on HAC,
2710*cbda039fSThomas Faber          * fact 4.48
2711*cbda039fSThomas Faber          */
2712*cbda039fSThomas Faber         rounds = ( ( nbits >= 1450 ) ?  4 : ( nbits >=  1150 ) ?  5 :
2713*cbda039fSThomas Faber                    ( nbits >= 1000 ) ?  6 : ( nbits >=   850 ) ?  7 :
2714*cbda039fSThomas Faber                    ( nbits >=  750 ) ?  8 : ( nbits >=   500 ) ? 13 :
2715*cbda039fSThomas Faber                    ( nbits >=  250 ) ? 28 : ( nbits >=   150 ) ? 40 : 51 );
2716*cbda039fSThomas Faber     }
27170ba5bc40SThomas Faber 
2718*cbda039fSThomas Faber     while( 1 )
2719*cbda039fSThomas Faber     {
2720c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2721*cbda039fSThomas Faber         /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2722*cbda039fSThomas Faber         if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2723c2c66affSColin Finck 
2724*cbda039fSThomas Faber         k = n * biL;
2725*cbda039fSThomas Faber         if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2726c2c66affSColin Finck         X->p[0] |= 1;
2727c2c66affSColin Finck 
2728*cbda039fSThomas Faber         if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
2729c2c66affSColin Finck         {
2730*cbda039fSThomas Faber             ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
2731*cbda039fSThomas Faber 
2732c2c66affSColin Finck             if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2733c2c66affSColin Finck                 goto cleanup;
2734c2c66affSColin Finck         }
2735c2c66affSColin Finck         else
2736c2c66affSColin Finck         {
2737c2c66affSColin Finck             /*
2738c2c66affSColin Finck              * An necessary condition for Y and X = 2Y + 1 to be prime
2739c2c66affSColin Finck              * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2740c2c66affSColin Finck              * Make sure it is satisfied, while keeping X = 3 mod 4
2741c2c66affSColin Finck              */
2742c2c66affSColin Finck 
2743c2c66affSColin Finck             X->p[0] |= 2;
2744c2c66affSColin Finck 
2745c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2746c2c66affSColin Finck             if( r == 0 )
2747c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2748c2c66affSColin Finck             else if( r == 1 )
2749c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2750c2c66affSColin Finck 
2751c2c66affSColin Finck             /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2752c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2753c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2754c2c66affSColin Finck 
2755c2c66affSColin Finck             while( 1 )
2756c2c66affSColin Finck             {
2757c2c66affSColin Finck                 /*
2758c2c66affSColin Finck                  * First, check small factors for X and Y
2759c2c66affSColin Finck                  * before doing Miller-Rabin on any of them
2760c2c66affSColin Finck                  */
2761c2c66affSColin Finck                 if( ( ret = mpi_check_small_factors(  X         ) ) == 0 &&
2762c2c66affSColin Finck                     ( ret = mpi_check_small_factors( &Y         ) ) == 0 &&
27630ba5bc40SThomas Faber                     ( ret = mpi_miller_rabin(  X, rounds, f_rng, p_rng  ) )
27640ba5bc40SThomas Faber                                                                     == 0 &&
27650ba5bc40SThomas Faber                     ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng  ) )
27660ba5bc40SThomas Faber                                                                     == 0 )
2767*cbda039fSThomas Faber                     goto cleanup;
2768c2c66affSColin Finck 
2769c2c66affSColin Finck                 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2770c2c66affSColin Finck                     goto cleanup;
2771c2c66affSColin Finck 
2772c2c66affSColin Finck                 /*
2773c2c66affSColin Finck                  * Next candidates. We want to preserve Y = (X-1) / 2 and
2774c2c66affSColin Finck                  * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2775c2c66affSColin Finck                  * so up Y by 6 and X by 12.
2776c2c66affSColin Finck                  */
2777c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(  X,  X, 12 ) );
2778c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6  ) );
2779c2c66affSColin Finck             }
2780c2c66affSColin Finck         }
2781*cbda039fSThomas Faber     }
2782c2c66affSColin Finck 
2783c2c66affSColin Finck cleanup:
2784c2c66affSColin Finck 
2785c2c66affSColin Finck     mbedtls_mpi_free( &Y );
2786c2c66affSColin Finck 
2787c2c66affSColin Finck     return( ret );
2788c2c66affSColin Finck }
2789c2c66affSColin Finck 
2790c2c66affSColin Finck #endif /* MBEDTLS_GENPRIME */
2791c2c66affSColin Finck 
2792c2c66affSColin Finck #if defined(MBEDTLS_SELF_TEST)
2793c2c66affSColin Finck 
2794c2c66affSColin Finck #define GCD_PAIR_COUNT  3
2795c2c66affSColin Finck 
2796c2c66affSColin Finck static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2797c2c66affSColin Finck {
2798c2c66affSColin Finck     { 693, 609, 21 },
2799c2c66affSColin Finck     { 1764, 868, 28 },
2800c2c66affSColin Finck     { 768454923, 542167814, 1 }
2801c2c66affSColin Finck };
2802c2c66affSColin Finck 
2803c2c66affSColin Finck /*
2804c2c66affSColin Finck  * Checkup routine
2805c2c66affSColin Finck  */
2806c2c66affSColin Finck int mbedtls_mpi_self_test( int verbose )
2807c2c66affSColin Finck {
2808c2c66affSColin Finck     int ret, i;
2809c2c66affSColin Finck     mbedtls_mpi A, E, N, X, Y, U, V;
2810c2c66affSColin Finck 
2811c2c66affSColin Finck     mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2812c2c66affSColin Finck     mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
2813c2c66affSColin Finck 
2814c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
2815c2c66affSColin Finck         "EFE021C2645FD1DC586E69184AF4A31E" \
2816c2c66affSColin Finck         "D5F53E93B5F123FA41680867BA110131" \
2817c2c66affSColin Finck         "944FE7952E2517337780CB0DB80E61AA" \
2818c2c66affSColin Finck         "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2819c2c66affSColin Finck 
2820c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
2821c2c66affSColin Finck         "B2E7EFD37075B9F03FF989C7C5051C20" \
2822c2c66affSColin Finck         "34D2A323810251127E7BF8625A4F49A5" \
2823c2c66affSColin Finck         "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2824c2c66affSColin Finck         "5B5C25763222FEFCCFC38B832366C29E" ) );
2825c2c66affSColin Finck 
2826c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
2827c2c66affSColin Finck         "0066A198186C18C10B2F5ED9B522752A" \
2828c2c66affSColin Finck         "9830B69916E535C8F047518A889A43A5" \
2829c2c66affSColin Finck         "94B6BED27A168D31D4A52F88925AA8F5" ) );
2830c2c66affSColin Finck 
2831c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
2832c2c66affSColin Finck 
2833c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
2834c2c66affSColin Finck         "602AB7ECA597A3D6B56FF9829A5E8B85" \
2835c2c66affSColin Finck         "9E857EA95A03512E2BAE7391688D264A" \
2836c2c66affSColin Finck         "A5663B0341DB9CCFD2C4C5F421FEC814" \
2837c2c66affSColin Finck         "8001B72E848A38CAE1C65F78E56ABDEF" \
2838c2c66affSColin Finck         "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2839c2c66affSColin Finck         "ECF677152EF804370C1A305CAF3B5BF1" \
2840c2c66affSColin Finck         "30879B56C61DE584A0F53A2447A51E" ) );
2841c2c66affSColin Finck 
2842c2c66affSColin Finck     if( verbose != 0 )
2843c2c66affSColin Finck         mbedtls_printf( "  MPI test #1 (mul_mpi): " );
2844c2c66affSColin Finck 
2845c2c66affSColin Finck     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
2846c2c66affSColin Finck     {
2847c2c66affSColin Finck         if( verbose != 0 )
2848c2c66affSColin Finck             mbedtls_printf( "failed\n" );
2849c2c66affSColin Finck 
2850c2c66affSColin Finck         ret = 1;
2851c2c66affSColin Finck         goto cleanup;
2852c2c66affSColin Finck     }
2853c2c66affSColin Finck 
2854c2c66affSColin Finck     if( verbose != 0 )
2855c2c66affSColin Finck         mbedtls_printf( "passed\n" );
2856c2c66affSColin Finck 
2857c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
2858c2c66affSColin Finck 
2859c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
2860c2c66affSColin Finck         "256567336059E52CAE22925474705F39A94" ) );
2861c2c66affSColin Finck 
2862c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
2863c2c66affSColin Finck         "6613F26162223DF488E9CD48CC132C7A" \
2864c2c66affSColin Finck         "0AC93C701B001B092E4E5B9F73BCD27B" \
2865c2c66affSColin Finck         "9EE50D0657C77F374E903CDFA4C642" ) );
2866c2c66affSColin Finck 
2867c2c66affSColin Finck     if( verbose != 0 )
2868c2c66affSColin Finck         mbedtls_printf( "  MPI test #2 (div_mpi): " );
2869c2c66affSColin Finck 
2870c2c66affSColin Finck     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2871c2c66affSColin Finck         mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
2872c2c66affSColin Finck     {
2873c2c66affSColin Finck         if( verbose != 0 )
2874c2c66affSColin Finck             mbedtls_printf( "failed\n" );
2875c2c66affSColin Finck 
2876c2c66affSColin Finck         ret = 1;
2877c2c66affSColin Finck         goto cleanup;
2878c2c66affSColin Finck     }
2879c2c66affSColin Finck 
2880c2c66affSColin Finck     if( verbose != 0 )
2881c2c66affSColin Finck         mbedtls_printf( "passed\n" );
2882c2c66affSColin Finck 
2883c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2884c2c66affSColin Finck 
2885c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
2886c2c66affSColin Finck         "36E139AEA55215609D2816998ED020BB" \
2887c2c66affSColin Finck         "BD96C37890F65171D948E9BC7CBAA4D9" \
2888c2c66affSColin Finck         "325D24D6A3C12710F10A09FA08AB87" ) );
2889c2c66affSColin Finck 
2890c2c66affSColin Finck     if( verbose != 0 )
2891c2c66affSColin Finck         mbedtls_printf( "  MPI test #3 (exp_mod): " );
2892c2c66affSColin Finck 
2893c2c66affSColin Finck     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
2894c2c66affSColin Finck     {
2895c2c66affSColin Finck         if( verbose != 0 )
2896c2c66affSColin Finck             mbedtls_printf( "failed\n" );
2897c2c66affSColin Finck 
2898c2c66affSColin Finck         ret = 1;
2899c2c66affSColin Finck         goto cleanup;
2900c2c66affSColin Finck     }
2901c2c66affSColin Finck 
2902c2c66affSColin Finck     if( verbose != 0 )
2903c2c66affSColin Finck         mbedtls_printf( "passed\n" );
2904c2c66affSColin Finck 
2905c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
2906c2c66affSColin Finck 
2907c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
2908c2c66affSColin Finck         "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2909c2c66affSColin Finck         "C3DBA76456363A10869622EAC2DD84EC" \
2910c2c66affSColin Finck         "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2911c2c66affSColin Finck 
2912c2c66affSColin Finck     if( verbose != 0 )
2913c2c66affSColin Finck         mbedtls_printf( "  MPI test #4 (inv_mod): " );
2914c2c66affSColin Finck 
2915c2c66affSColin Finck     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
2916c2c66affSColin Finck     {
2917c2c66affSColin Finck         if( verbose != 0 )
2918c2c66affSColin Finck             mbedtls_printf( "failed\n" );
2919c2c66affSColin Finck 
2920c2c66affSColin Finck         ret = 1;
2921c2c66affSColin Finck         goto cleanup;
2922c2c66affSColin Finck     }
2923c2c66affSColin Finck 
2924c2c66affSColin Finck     if( verbose != 0 )
2925c2c66affSColin Finck         mbedtls_printf( "passed\n" );
2926c2c66affSColin Finck 
2927c2c66affSColin Finck     if( verbose != 0 )
2928c2c66affSColin Finck         mbedtls_printf( "  MPI test #5 (simple gcd): " );
2929c2c66affSColin Finck 
2930c2c66affSColin Finck     for( i = 0; i < GCD_PAIR_COUNT; i++ )
2931c2c66affSColin Finck     {
2932c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2933c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
2934c2c66affSColin Finck 
2935c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
2936c2c66affSColin Finck 
2937c2c66affSColin Finck         if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2938c2c66affSColin Finck         {
2939c2c66affSColin Finck             if( verbose != 0 )
2940c2c66affSColin Finck                 mbedtls_printf( "failed at %d\n", i );
2941c2c66affSColin Finck 
2942c2c66affSColin Finck             ret = 1;
2943c2c66affSColin Finck             goto cleanup;
2944c2c66affSColin Finck         }
2945c2c66affSColin Finck     }
2946c2c66affSColin Finck 
2947c2c66affSColin Finck     if( verbose != 0 )
2948c2c66affSColin Finck         mbedtls_printf( "passed\n" );
2949c2c66affSColin Finck 
2950c2c66affSColin Finck cleanup:
2951c2c66affSColin Finck 
2952c2c66affSColin Finck     if( ret != 0 && verbose != 0 )
2953c2c66affSColin Finck         mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
2954c2c66affSColin Finck 
2955c2c66affSColin Finck     mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2956c2c66affSColin Finck     mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
2957c2c66affSColin Finck 
2958c2c66affSColin Finck     if( verbose != 0 )
2959c2c66affSColin Finck         mbedtls_printf( "\n" );
2960c2c66affSColin Finck 
2961c2c66affSColin Finck     return( ret );
2962c2c66affSColin Finck }
2963c2c66affSColin Finck 
2964c2c66affSColin Finck #endif /* MBEDTLS_SELF_TEST */
2965c2c66affSColin Finck 
2966c2c66affSColin Finck #endif /* MBEDTLS_BIGNUM_C */
2967