xref: /reactos/dll/3rdparty/mbedtls/bignum.c (revision d152519a)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  *  Multi-precision integer library
3c2c66affSColin Finck  *
4c2c66affSColin Finck  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5c2c66affSColin Finck  *  SPDX-License-Identifier: GPL-2.0
6c2c66affSColin Finck  *
7c2c66affSColin Finck  *  This program is free software; you can redistribute it and/or modify
8c2c66affSColin Finck  *  it under the terms of the GNU General Public License as published by
9c2c66affSColin Finck  *  the Free Software Foundation; either version 2 of the License, or
10c2c66affSColin Finck  *  (at your option) any later version.
11c2c66affSColin Finck  *
12c2c66affSColin Finck  *  This program is distributed in the hope that it will be useful,
13c2c66affSColin Finck  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14c2c66affSColin Finck  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15c2c66affSColin Finck  *  GNU General Public License for more details.
16c2c66affSColin Finck  *
17c2c66affSColin Finck  *  You should have received a copy of the GNU General Public License along
18c2c66affSColin Finck  *  with this program; if not, write to the Free Software Foundation, Inc.,
19c2c66affSColin Finck  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20c2c66affSColin Finck  *
21c2c66affSColin Finck  *  This file is part of mbed TLS (https://tls.mbed.org)
22c2c66affSColin Finck  */
23c2c66affSColin Finck 
24c2c66affSColin Finck /*
25c2c66affSColin Finck  *  The following sources were referenced in the design of this Multi-precision
26c2c66affSColin Finck  *  Integer library:
27c2c66affSColin Finck  *
28c2c66affSColin Finck  *  [1] Handbook of Applied Cryptography - 1997
29c2c66affSColin Finck  *      Menezes, van Oorschot and Vanstone
30c2c66affSColin Finck  *
31c2c66affSColin Finck  *  [2] Multi-Precision Math
32c2c66affSColin Finck  *      Tom St Denis
33c2c66affSColin Finck  *      https://github.com/libtom/libtommath/blob/develop/tommath.pdf
34c2c66affSColin Finck  *
35c2c66affSColin Finck  *  [3] GNU Multi-Precision Arithmetic Library
36c2c66affSColin Finck  *      https://gmplib.org/manual/index.html
37c2c66affSColin Finck  *
38c2c66affSColin Finck  */
39c2c66affSColin Finck 
40c2c66affSColin Finck #if !defined(MBEDTLS_CONFIG_FILE)
41c2c66affSColin Finck #include "mbedtls/config.h"
42c2c66affSColin Finck #else
43c2c66affSColin Finck #include MBEDTLS_CONFIG_FILE
44c2c66affSColin Finck #endif
45c2c66affSColin Finck 
46c2c66affSColin Finck #if defined(MBEDTLS_BIGNUM_C)
47c2c66affSColin Finck 
48c2c66affSColin Finck #include "mbedtls/bignum.h"
49c2c66affSColin Finck #include "mbedtls/bn_mul.h"
50c2c66affSColin Finck 
51c2c66affSColin Finck #include <string.h>
52c2c66affSColin Finck 
53c2c66affSColin Finck #if defined(MBEDTLS_PLATFORM_C)
54c2c66affSColin Finck #include "mbedtls/platform.h"
55c2c66affSColin Finck #else
56c2c66affSColin Finck #include <stdio.h>
57c2c66affSColin Finck #include <stdlib.h>
58c2c66affSColin Finck #define mbedtls_printf     printf
59c2c66affSColin Finck #define mbedtls_calloc    calloc
60c2c66affSColin Finck #define mbedtls_free       free
61c2c66affSColin Finck #endif
62c2c66affSColin Finck 
63c2c66affSColin Finck /* Implementation that should never be optimized out by the compiler */
64c2c66affSColin Finck static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) {
65c2c66affSColin Finck     volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0;
66c2c66affSColin Finck }
67c2c66affSColin Finck 
68d9e6c9b5SThomas Faber /* Implementation that should never be optimized out by the compiler */
69d9e6c9b5SThomas Faber static void mbedtls_zeroize( void *v, size_t n ) {
70d9e6c9b5SThomas Faber     volatile unsigned char *p = v; while( n-- ) *p++ = 0;
71d9e6c9b5SThomas Faber }
72d9e6c9b5SThomas Faber 
73c2c66affSColin Finck #define ciL    (sizeof(mbedtls_mpi_uint))         /* chars in limb  */
74c2c66affSColin Finck #define biL    (ciL << 3)               /* bits  in limb  */
75c2c66affSColin Finck #define biH    (ciL << 2)               /* half limb size */
76c2c66affSColin Finck 
77c2c66affSColin Finck #define MPI_SIZE_T_MAX  ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
78c2c66affSColin Finck 
79c2c66affSColin Finck /*
80c2c66affSColin Finck  * Convert between bits/chars and number of limbs
81c2c66affSColin Finck  * Divide first in order to avoid potential overflows
82c2c66affSColin Finck  */
83c2c66affSColin Finck #define BITS_TO_LIMBS(i)  ( (i) / biL + ( (i) % biL != 0 ) )
84c2c66affSColin Finck #define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
85c2c66affSColin Finck 
86c2c66affSColin Finck /*
87c2c66affSColin Finck  * Initialize one MPI
88c2c66affSColin Finck  */
89c2c66affSColin Finck void mbedtls_mpi_init( mbedtls_mpi *X )
90c2c66affSColin Finck {
91c2c66affSColin Finck     if( X == NULL )
92c2c66affSColin Finck         return;
93c2c66affSColin Finck 
94c2c66affSColin Finck     X->s = 1;
95c2c66affSColin Finck     X->n = 0;
96c2c66affSColin Finck     X->p = NULL;
97c2c66affSColin Finck }
98c2c66affSColin Finck 
99c2c66affSColin Finck /*
100c2c66affSColin Finck  * Unallocate one MPI
101c2c66affSColin Finck  */
102c2c66affSColin Finck void mbedtls_mpi_free( mbedtls_mpi *X )
103c2c66affSColin Finck {
104c2c66affSColin Finck     if( X == NULL )
105c2c66affSColin Finck         return;
106c2c66affSColin Finck 
107c2c66affSColin Finck     if( X->p != NULL )
108c2c66affSColin Finck     {
109c2c66affSColin Finck         mbedtls_mpi_zeroize( X->p, X->n );
110c2c66affSColin Finck         mbedtls_free( X->p );
111c2c66affSColin Finck     }
112c2c66affSColin Finck 
113c2c66affSColin Finck     X->s = 1;
114c2c66affSColin Finck     X->n = 0;
115c2c66affSColin Finck     X->p = NULL;
116c2c66affSColin Finck }
117c2c66affSColin Finck 
118c2c66affSColin Finck /*
119c2c66affSColin Finck  * Enlarge to the specified number of limbs
120c2c66affSColin Finck  */
121c2c66affSColin Finck int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
122c2c66affSColin Finck {
123c2c66affSColin Finck     mbedtls_mpi_uint *p;
124c2c66affSColin Finck 
125c2c66affSColin Finck     if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
126c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
127c2c66affSColin Finck 
128c2c66affSColin Finck     if( X->n < nblimbs )
129c2c66affSColin Finck     {
130c2c66affSColin Finck         if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
131c2c66affSColin Finck             return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
132c2c66affSColin Finck 
133c2c66affSColin Finck         if( X->p != NULL )
134c2c66affSColin Finck         {
135c2c66affSColin Finck             memcpy( p, X->p, X->n * ciL );
136c2c66affSColin Finck             mbedtls_mpi_zeroize( X->p, X->n );
137c2c66affSColin Finck             mbedtls_free( X->p );
138c2c66affSColin Finck         }
139c2c66affSColin Finck 
140c2c66affSColin Finck         X->n = nblimbs;
141c2c66affSColin Finck         X->p = p;
142c2c66affSColin Finck     }
143c2c66affSColin Finck 
144c2c66affSColin Finck     return( 0 );
145c2c66affSColin Finck }
146c2c66affSColin Finck 
147c2c66affSColin Finck /*
148c2c66affSColin Finck  * Resize down as much as possible,
149c2c66affSColin Finck  * while keeping at least the specified number of limbs
150c2c66affSColin Finck  */
151c2c66affSColin Finck int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
152c2c66affSColin Finck {
153c2c66affSColin Finck     mbedtls_mpi_uint *p;
154c2c66affSColin Finck     size_t i;
155c2c66affSColin Finck 
156c2c66affSColin Finck     /* Actually resize up in this case */
157c2c66affSColin Finck     if( X->n <= nblimbs )
158c2c66affSColin Finck         return( mbedtls_mpi_grow( X, nblimbs ) );
159c2c66affSColin Finck 
160c2c66affSColin Finck     for( i = X->n - 1; i > 0; i-- )
161c2c66affSColin Finck         if( X->p[i] != 0 )
162c2c66affSColin Finck             break;
163c2c66affSColin Finck     i++;
164c2c66affSColin Finck 
165c2c66affSColin Finck     if( i < nblimbs )
166c2c66affSColin Finck         i = nblimbs;
167c2c66affSColin Finck 
168c2c66affSColin Finck     if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
169c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
170c2c66affSColin Finck 
171c2c66affSColin Finck     if( X->p != NULL )
172c2c66affSColin Finck     {
173c2c66affSColin Finck         memcpy( p, X->p, i * ciL );
174c2c66affSColin Finck         mbedtls_mpi_zeroize( X->p, X->n );
175c2c66affSColin Finck         mbedtls_free( X->p );
176c2c66affSColin Finck     }
177c2c66affSColin Finck 
178c2c66affSColin Finck     X->n = i;
179c2c66affSColin Finck     X->p = p;
180c2c66affSColin Finck 
181c2c66affSColin Finck     return( 0 );
182c2c66affSColin Finck }
183c2c66affSColin Finck 
184c2c66affSColin Finck /*
185c2c66affSColin Finck  * Copy the contents of Y into X
186c2c66affSColin Finck  */
187c2c66affSColin Finck int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
188c2c66affSColin Finck {
189c2c66affSColin Finck     int ret;
190c2c66affSColin Finck     size_t i;
191c2c66affSColin Finck 
192c2c66affSColin Finck     if( X == Y )
193c2c66affSColin Finck         return( 0 );
194c2c66affSColin Finck 
195c2c66affSColin Finck     if( Y->p == NULL )
196c2c66affSColin Finck     {
197c2c66affSColin Finck         mbedtls_mpi_free( X );
198c2c66affSColin Finck         return( 0 );
199c2c66affSColin Finck     }
200c2c66affSColin Finck 
201c2c66affSColin Finck     for( i = Y->n - 1; i > 0; i-- )
202c2c66affSColin Finck         if( Y->p[i] != 0 )
203c2c66affSColin Finck             break;
204c2c66affSColin Finck     i++;
205c2c66affSColin Finck 
206c2c66affSColin Finck     X->s = Y->s;
207c2c66affSColin Finck 
208c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
209c2c66affSColin Finck 
210c2c66affSColin Finck     memset( X->p, 0, X->n * ciL );
211c2c66affSColin Finck     memcpy( X->p, Y->p, i * ciL );
212c2c66affSColin Finck 
213c2c66affSColin Finck cleanup:
214c2c66affSColin Finck 
215c2c66affSColin Finck     return( ret );
216c2c66affSColin Finck }
217c2c66affSColin Finck 
218c2c66affSColin Finck /*
219c2c66affSColin Finck  * Swap the contents of X and Y
220c2c66affSColin Finck  */
221c2c66affSColin Finck void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
222c2c66affSColin Finck {
223c2c66affSColin Finck     mbedtls_mpi T;
224c2c66affSColin Finck 
225c2c66affSColin Finck     memcpy( &T,  X, sizeof( mbedtls_mpi ) );
226c2c66affSColin Finck     memcpy(  X,  Y, sizeof( mbedtls_mpi ) );
227c2c66affSColin Finck     memcpy(  Y, &T, sizeof( mbedtls_mpi ) );
228c2c66affSColin Finck }
229c2c66affSColin Finck 
230c2c66affSColin Finck /*
231c2c66affSColin Finck  * Conditionally assign X = Y, without leaking information
232c2c66affSColin Finck  * about whether the assignment was made or not.
233c2c66affSColin Finck  * (Leaking information about the respective sizes of X and Y is ok however.)
234c2c66affSColin Finck  */
235c2c66affSColin Finck int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
236c2c66affSColin Finck {
237c2c66affSColin Finck     int ret = 0;
238c2c66affSColin Finck     size_t i;
239c2c66affSColin Finck 
240c2c66affSColin Finck     /* make sure assign is 0 or 1 in a time-constant manner */
241c2c66affSColin Finck     assign = (assign | (unsigned char)-assign) >> 7;
242c2c66affSColin Finck 
243c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
244c2c66affSColin Finck 
245c2c66affSColin Finck     X->s = X->s * ( 1 - assign ) + Y->s * assign;
246c2c66affSColin Finck 
247c2c66affSColin Finck     for( i = 0; i < Y->n; i++ )
248c2c66affSColin Finck         X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
249c2c66affSColin Finck 
250c2c66affSColin Finck     for( ; i < X->n; i++ )
251c2c66affSColin Finck         X->p[i] *= ( 1 - assign );
252c2c66affSColin Finck 
253c2c66affSColin Finck cleanup:
254c2c66affSColin Finck     return( ret );
255c2c66affSColin Finck }
256c2c66affSColin Finck 
257c2c66affSColin Finck /*
258c2c66affSColin Finck  * Conditionally swap X and Y, without leaking information
259c2c66affSColin Finck  * about whether the swap was made or not.
260c2c66affSColin Finck  * Here it is not ok to simply swap the pointers, which whould lead to
261c2c66affSColin Finck  * different memory access patterns when X and Y are used afterwards.
262c2c66affSColin Finck  */
263c2c66affSColin Finck int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
264c2c66affSColin Finck {
265c2c66affSColin Finck     int ret, s;
266c2c66affSColin Finck     size_t i;
267c2c66affSColin Finck     mbedtls_mpi_uint tmp;
268c2c66affSColin Finck 
269c2c66affSColin Finck     if( X == Y )
270c2c66affSColin Finck         return( 0 );
271c2c66affSColin Finck 
272c2c66affSColin Finck     /* make sure swap is 0 or 1 in a time-constant manner */
273c2c66affSColin Finck     swap = (swap | (unsigned char)-swap) >> 7;
274c2c66affSColin Finck 
275c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
276c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
277c2c66affSColin Finck 
278c2c66affSColin Finck     s = X->s;
279c2c66affSColin Finck     X->s = X->s * ( 1 - swap ) + Y->s * swap;
280c2c66affSColin Finck     Y->s = Y->s * ( 1 - swap ) +    s * swap;
281c2c66affSColin Finck 
282c2c66affSColin Finck 
283c2c66affSColin Finck     for( i = 0; i < X->n; i++ )
284c2c66affSColin Finck     {
285c2c66affSColin Finck         tmp = X->p[i];
286c2c66affSColin Finck         X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
287c2c66affSColin Finck         Y->p[i] = Y->p[i] * ( 1 - swap ) +     tmp * swap;
288c2c66affSColin Finck     }
289c2c66affSColin Finck 
290c2c66affSColin Finck cleanup:
291c2c66affSColin Finck     return( ret );
292c2c66affSColin Finck }
293c2c66affSColin Finck 
294c2c66affSColin Finck /*
295c2c66affSColin Finck  * Set value from integer
296c2c66affSColin Finck  */
297c2c66affSColin Finck int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
298c2c66affSColin Finck {
299c2c66affSColin Finck     int ret;
300c2c66affSColin Finck 
301c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
302c2c66affSColin Finck     memset( X->p, 0, X->n * ciL );
303c2c66affSColin Finck 
304c2c66affSColin Finck     X->p[0] = ( z < 0 ) ? -z : z;
305c2c66affSColin Finck     X->s    = ( z < 0 ) ? -1 : 1;
306c2c66affSColin Finck 
307c2c66affSColin Finck cleanup:
308c2c66affSColin Finck 
309c2c66affSColin Finck     return( ret );
310c2c66affSColin Finck }
311c2c66affSColin Finck 
312c2c66affSColin Finck /*
313c2c66affSColin Finck  * Get a specific bit
314c2c66affSColin Finck  */
315c2c66affSColin Finck int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
316c2c66affSColin Finck {
317c2c66affSColin Finck     if( X->n * biL <= pos )
318c2c66affSColin Finck         return( 0 );
319c2c66affSColin Finck 
320c2c66affSColin Finck     return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
321c2c66affSColin Finck }
322c2c66affSColin Finck 
3230ba5bc40SThomas Faber /* Get a specific byte, without range checks. */
3240ba5bc40SThomas Faber #define GET_BYTE( X, i )                                \
3250ba5bc40SThomas Faber     ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
3260ba5bc40SThomas Faber 
327c2c66affSColin Finck /*
328c2c66affSColin Finck  * Set a bit to a specific value of 0 or 1
329c2c66affSColin Finck  */
330c2c66affSColin Finck int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
331c2c66affSColin Finck {
332c2c66affSColin Finck     int ret = 0;
333c2c66affSColin Finck     size_t off = pos / biL;
334c2c66affSColin Finck     size_t idx = pos % biL;
335c2c66affSColin Finck 
336c2c66affSColin Finck     if( val != 0 && val != 1 )
337c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
338c2c66affSColin Finck 
339c2c66affSColin Finck     if( X->n * biL <= pos )
340c2c66affSColin Finck     {
341c2c66affSColin Finck         if( val == 0 )
342c2c66affSColin Finck             return( 0 );
343c2c66affSColin Finck 
344c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
345c2c66affSColin Finck     }
346c2c66affSColin Finck 
347c2c66affSColin Finck     X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
348c2c66affSColin Finck     X->p[off] |= (mbedtls_mpi_uint) val << idx;
349c2c66affSColin Finck 
350c2c66affSColin Finck cleanup:
351c2c66affSColin Finck 
352c2c66affSColin Finck     return( ret );
353c2c66affSColin Finck }
354c2c66affSColin Finck 
355c2c66affSColin Finck /*
356c2c66affSColin Finck  * Return the number of less significant zero-bits
357c2c66affSColin Finck  */
358c2c66affSColin Finck size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
359c2c66affSColin Finck {
360c2c66affSColin Finck     size_t i, j, count = 0;
361c2c66affSColin Finck 
362c2c66affSColin Finck     for( i = 0; i < X->n; i++ )
363c2c66affSColin Finck         for( j = 0; j < biL; j++, count++ )
364c2c66affSColin Finck             if( ( ( X->p[i] >> j ) & 1 ) != 0 )
365c2c66affSColin Finck                 return( count );
366c2c66affSColin Finck 
367c2c66affSColin Finck     return( 0 );
368c2c66affSColin Finck }
369c2c66affSColin Finck 
370c2c66affSColin Finck /*
371c2c66affSColin Finck  * Count leading zero bits in a given integer
372c2c66affSColin Finck  */
373c2c66affSColin Finck static size_t mbedtls_clz( const mbedtls_mpi_uint x )
374c2c66affSColin Finck {
375c2c66affSColin Finck     size_t j;
376c2c66affSColin Finck     mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
377c2c66affSColin Finck 
378c2c66affSColin Finck     for( j = 0; j < biL; j++ )
379c2c66affSColin Finck     {
380c2c66affSColin Finck         if( x & mask ) break;
381c2c66affSColin Finck 
382c2c66affSColin Finck         mask >>= 1;
383c2c66affSColin Finck     }
384c2c66affSColin Finck 
385c2c66affSColin Finck     return j;
386c2c66affSColin Finck }
387c2c66affSColin Finck 
388c2c66affSColin Finck /*
389c2c66affSColin Finck  * Return the number of bits
390c2c66affSColin Finck  */
391c2c66affSColin Finck size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
392c2c66affSColin Finck {
393c2c66affSColin Finck     size_t i, j;
394c2c66affSColin Finck 
395c2c66affSColin Finck     if( X->n == 0 )
396c2c66affSColin Finck         return( 0 );
397c2c66affSColin Finck 
398c2c66affSColin Finck     for( i = X->n - 1; i > 0; i-- )
399c2c66affSColin Finck         if( X->p[i] != 0 )
400c2c66affSColin Finck             break;
401c2c66affSColin Finck 
402c2c66affSColin Finck     j = biL - mbedtls_clz( X->p[i] );
403c2c66affSColin Finck 
404c2c66affSColin Finck     return( ( i * biL ) + j );
405c2c66affSColin Finck }
406c2c66affSColin Finck 
407c2c66affSColin Finck /*
408c2c66affSColin Finck  * Return the total size in bytes
409c2c66affSColin Finck  */
410c2c66affSColin Finck size_t mbedtls_mpi_size( const mbedtls_mpi *X )
411c2c66affSColin Finck {
412c2c66affSColin Finck     return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
413c2c66affSColin Finck }
414c2c66affSColin Finck 
415c2c66affSColin Finck /*
416c2c66affSColin Finck  * Convert an ASCII character to digit value
417c2c66affSColin Finck  */
418c2c66affSColin Finck static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
419c2c66affSColin Finck {
420c2c66affSColin Finck     *d = 255;
421c2c66affSColin Finck 
422c2c66affSColin Finck     if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
423c2c66affSColin Finck     if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
424c2c66affSColin Finck     if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
425c2c66affSColin Finck 
426c2c66affSColin Finck     if( *d >= (mbedtls_mpi_uint) radix )
427c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
428c2c66affSColin Finck 
429c2c66affSColin Finck     return( 0 );
430c2c66affSColin Finck }
431c2c66affSColin Finck 
432c2c66affSColin Finck /*
433c2c66affSColin Finck  * Import from an ASCII string
434c2c66affSColin Finck  */
435c2c66affSColin Finck int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
436c2c66affSColin Finck {
437c2c66affSColin Finck     int ret;
438c2c66affSColin Finck     size_t i, j, slen, n;
439c2c66affSColin Finck     mbedtls_mpi_uint d;
440c2c66affSColin Finck     mbedtls_mpi T;
441c2c66affSColin Finck 
442c2c66affSColin Finck     if( radix < 2 || radix > 16 )
443c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
444c2c66affSColin Finck 
445c2c66affSColin Finck     mbedtls_mpi_init( &T );
446c2c66affSColin Finck 
447c2c66affSColin Finck     slen = strlen( s );
448c2c66affSColin Finck 
449c2c66affSColin Finck     if( radix == 16 )
450c2c66affSColin Finck     {
451c2c66affSColin Finck         if( slen > MPI_SIZE_T_MAX >> 2 )
452c2c66affSColin Finck             return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
453c2c66affSColin Finck 
454c2c66affSColin Finck         n = BITS_TO_LIMBS( slen << 2 );
455c2c66affSColin Finck 
456c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
457c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
458c2c66affSColin Finck 
459c2c66affSColin Finck         for( i = slen, j = 0; i > 0; i--, j++ )
460c2c66affSColin Finck         {
461c2c66affSColin Finck             if( i == 1 && s[i - 1] == '-' )
462c2c66affSColin Finck             {
463c2c66affSColin Finck                 X->s = -1;
464c2c66affSColin Finck                 break;
465c2c66affSColin Finck             }
466c2c66affSColin Finck 
467c2c66affSColin Finck             MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
468c2c66affSColin Finck             X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
469c2c66affSColin Finck         }
470c2c66affSColin Finck     }
471c2c66affSColin Finck     else
472c2c66affSColin Finck     {
473c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
474c2c66affSColin Finck 
475c2c66affSColin Finck         for( i = 0; i < slen; i++ )
476c2c66affSColin Finck         {
477c2c66affSColin Finck             if( i == 0 && s[i] == '-' )
478c2c66affSColin Finck             {
479c2c66affSColin Finck                 X->s = -1;
480c2c66affSColin Finck                 continue;
481c2c66affSColin Finck             }
482c2c66affSColin Finck 
483c2c66affSColin Finck             MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
484c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
485c2c66affSColin Finck 
486c2c66affSColin Finck             if( X->s == 1 )
487c2c66affSColin Finck             {
488c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
489c2c66affSColin Finck             }
490c2c66affSColin Finck             else
491c2c66affSColin Finck             {
492c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
493c2c66affSColin Finck             }
494c2c66affSColin Finck         }
495c2c66affSColin Finck     }
496c2c66affSColin Finck 
497c2c66affSColin Finck cleanup:
498c2c66affSColin Finck 
499c2c66affSColin Finck     mbedtls_mpi_free( &T );
500c2c66affSColin Finck 
501c2c66affSColin Finck     return( ret );
502c2c66affSColin Finck }
503c2c66affSColin Finck 
504c2c66affSColin Finck /*
505ca86ee9cSThomas Faber  * Helper to write the digits high-order first.
506c2c66affSColin Finck  */
507ca86ee9cSThomas Faber static int mpi_write_hlp( mbedtls_mpi *X, int radix,
508ca86ee9cSThomas Faber                           char **p, const size_t buflen )
509c2c66affSColin Finck {
510c2c66affSColin Finck     int ret;
511c2c66affSColin Finck     mbedtls_mpi_uint r;
512ca86ee9cSThomas Faber     size_t length = 0;
513ca86ee9cSThomas Faber     char *p_end = *p + buflen;
514c2c66affSColin Finck 
515ca86ee9cSThomas Faber     do
516ca86ee9cSThomas Faber     {
517ca86ee9cSThomas Faber         if( length >= buflen )
518ca86ee9cSThomas Faber         {
519ca86ee9cSThomas Faber             return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
520ca86ee9cSThomas Faber         }
521c2c66affSColin Finck 
522c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
523c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
524ca86ee9cSThomas Faber         /*
525ca86ee9cSThomas Faber          * Write the residue in the current position, as an ASCII character.
526ca86ee9cSThomas Faber          */
527ca86ee9cSThomas Faber         if( r < 0xA )
528ca86ee9cSThomas Faber             *(--p_end) = (char)( '0' + r );
529c2c66affSColin Finck         else
530ca86ee9cSThomas Faber             *(--p_end) = (char)( 'A' + ( r - 0xA ) );
531ca86ee9cSThomas Faber 
532ca86ee9cSThomas Faber         length++;
533ca86ee9cSThomas Faber     } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
534ca86ee9cSThomas Faber 
535ca86ee9cSThomas Faber     memmove( *p, p_end, length );
536ca86ee9cSThomas Faber     *p += length;
537c2c66affSColin Finck 
538c2c66affSColin Finck cleanup:
539c2c66affSColin Finck 
540c2c66affSColin Finck     return( ret );
541c2c66affSColin Finck }
542c2c66affSColin Finck 
543c2c66affSColin Finck /*
544c2c66affSColin Finck  * Export into an ASCII string
545c2c66affSColin Finck  */
546c2c66affSColin Finck int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
547c2c66affSColin Finck                               char *buf, size_t buflen, size_t *olen )
548c2c66affSColin Finck {
549c2c66affSColin Finck     int ret = 0;
550c2c66affSColin Finck     size_t n;
551c2c66affSColin Finck     char *p;
552c2c66affSColin Finck     mbedtls_mpi T;
553c2c66affSColin Finck 
554c2c66affSColin Finck     if( radix < 2 || radix > 16 )
555c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
556c2c66affSColin Finck 
557430656f0SThomas Faber     n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
558430656f0SThomas Faber     if( radix >=  4 ) n >>= 1;   /* Number of 4-adic digits necessary to present
559430656f0SThomas Faber                                   * `n`. If radix > 4, this might be a strict
560430656f0SThomas Faber                                   * overapproximation of the number of
561430656f0SThomas Faber                                   * radix-adic digits needed to present `n`. */
562430656f0SThomas Faber     if( radix >= 16 ) n >>= 1;   /* Number of hexadecimal digits necessary to
563430656f0SThomas Faber                                   * present `n`. */
564430656f0SThomas Faber 
565430656f0SThomas Faber     n += 1; /* Terminating null byte */
566430656f0SThomas Faber     n += 1; /* Compensate for the divisions above, which round down `n`
567430656f0SThomas Faber              * in case it's not even. */
568430656f0SThomas Faber     n += 1; /* Potential '-'-sign. */
569430656f0SThomas Faber     n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
570430656f0SThomas Faber                      * which always uses an even number of hex-digits. */
571c2c66affSColin Finck 
572c2c66affSColin Finck     if( buflen < n )
573c2c66affSColin Finck     {
574c2c66affSColin Finck         *olen = n;
575c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
576c2c66affSColin Finck     }
577c2c66affSColin Finck 
578c2c66affSColin Finck     p = buf;
579c2c66affSColin Finck     mbedtls_mpi_init( &T );
580c2c66affSColin Finck 
581c2c66affSColin Finck     if( X->s == -1 )
582430656f0SThomas Faber     {
583c2c66affSColin Finck         *p++ = '-';
584430656f0SThomas Faber         buflen--;
585430656f0SThomas Faber     }
586c2c66affSColin Finck 
587c2c66affSColin Finck     if( radix == 16 )
588c2c66affSColin Finck     {
589c2c66affSColin Finck         int c;
590c2c66affSColin Finck         size_t i, j, k;
591c2c66affSColin Finck 
592c2c66affSColin Finck         for( i = X->n, k = 0; i > 0; i-- )
593c2c66affSColin Finck         {
594c2c66affSColin Finck             for( j = ciL; j > 0; j-- )
595c2c66affSColin Finck             {
596c2c66affSColin Finck                 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
597c2c66affSColin Finck 
598c2c66affSColin Finck                 if( c == 0 && k == 0 && ( i + j ) != 2 )
599c2c66affSColin Finck                     continue;
600c2c66affSColin Finck 
601c2c66affSColin Finck                 *(p++) = "0123456789ABCDEF" [c / 16];
602c2c66affSColin Finck                 *(p++) = "0123456789ABCDEF" [c % 16];
603c2c66affSColin Finck                 k = 1;
604c2c66affSColin Finck             }
605c2c66affSColin Finck         }
606c2c66affSColin Finck     }
607c2c66affSColin Finck     else
608c2c66affSColin Finck     {
609c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
610c2c66affSColin Finck 
611c2c66affSColin Finck         if( T.s == -1 )
612c2c66affSColin Finck             T.s = 1;
613c2c66affSColin Finck 
614ca86ee9cSThomas Faber         MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
615c2c66affSColin Finck     }
616c2c66affSColin Finck 
617c2c66affSColin Finck     *p++ = '\0';
618c2c66affSColin Finck     *olen = p - buf;
619c2c66affSColin Finck 
620c2c66affSColin Finck cleanup:
621c2c66affSColin Finck 
622c2c66affSColin Finck     mbedtls_mpi_free( &T );
623c2c66affSColin Finck 
624c2c66affSColin Finck     return( ret );
625c2c66affSColin Finck }
626c2c66affSColin Finck 
627c2c66affSColin Finck #if defined(MBEDTLS_FS_IO)
628c2c66affSColin Finck /*
629c2c66affSColin Finck  * Read X from an opened file
630c2c66affSColin Finck  */
631c2c66affSColin Finck int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
632c2c66affSColin Finck {
633c2c66affSColin Finck     mbedtls_mpi_uint d;
634c2c66affSColin Finck     size_t slen;
635c2c66affSColin Finck     char *p;
636c2c66affSColin Finck     /*
637c2c66affSColin Finck      * Buffer should have space for (short) label and decimal formatted MPI,
638c2c66affSColin Finck      * newline characters and '\0'
639c2c66affSColin Finck      */
640c2c66affSColin Finck     char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
641c2c66affSColin Finck 
642c2c66affSColin Finck     memset( s, 0, sizeof( s ) );
643c2c66affSColin Finck     if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
644c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
645c2c66affSColin Finck 
646c2c66affSColin Finck     slen = strlen( s );
647c2c66affSColin Finck     if( slen == sizeof( s ) - 2 )
648c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
649c2c66affSColin Finck 
650c2c66affSColin Finck     if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
651c2c66affSColin Finck     if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
652c2c66affSColin Finck 
653c2c66affSColin Finck     p = s + slen;
654c2c66affSColin Finck     while( p-- > s )
655c2c66affSColin Finck         if( mpi_get_digit( &d, radix, *p ) != 0 )
656c2c66affSColin Finck             break;
657c2c66affSColin Finck 
658c2c66affSColin Finck     return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
659c2c66affSColin Finck }
660c2c66affSColin Finck 
661c2c66affSColin Finck /*
662c2c66affSColin Finck  * Write X into an opened file (or stdout if fout == NULL)
663c2c66affSColin Finck  */
664c2c66affSColin Finck int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
665c2c66affSColin Finck {
666c2c66affSColin Finck     int ret;
667c2c66affSColin Finck     size_t n, slen, plen;
668c2c66affSColin Finck     /*
669c2c66affSColin Finck      * Buffer should have space for (short) label and decimal formatted MPI,
670c2c66affSColin Finck      * newline characters and '\0'
671c2c66affSColin Finck      */
672c2c66affSColin Finck     char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
673c2c66affSColin Finck 
674c2c66affSColin Finck     memset( s, 0, sizeof( s ) );
675c2c66affSColin Finck 
676c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
677c2c66affSColin Finck 
678c2c66affSColin Finck     if( p == NULL ) p = "";
679c2c66affSColin Finck 
680c2c66affSColin Finck     plen = strlen( p );
681c2c66affSColin Finck     slen = strlen( s );
682c2c66affSColin Finck     s[slen++] = '\r';
683c2c66affSColin Finck     s[slen++] = '\n';
684c2c66affSColin Finck 
685c2c66affSColin Finck     if( fout != NULL )
686c2c66affSColin Finck     {
687c2c66affSColin Finck         if( fwrite( p, 1, plen, fout ) != plen ||
688c2c66affSColin Finck             fwrite( s, 1, slen, fout ) != slen )
689c2c66affSColin Finck             return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
690c2c66affSColin Finck     }
691c2c66affSColin Finck     else
692c2c66affSColin Finck         mbedtls_printf( "%s%s", p, s );
693c2c66affSColin Finck 
694c2c66affSColin Finck cleanup:
695c2c66affSColin Finck 
696c2c66affSColin Finck     return( ret );
697c2c66affSColin Finck }
698c2c66affSColin Finck #endif /* MBEDTLS_FS_IO */
699c2c66affSColin Finck 
700c2c66affSColin Finck /*
701c2c66affSColin Finck  * Import X from unsigned binary data, big endian
702c2c66affSColin Finck  */
703c2c66affSColin Finck int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
704c2c66affSColin Finck {
705c2c66affSColin Finck     int ret;
706d9e6c9b5SThomas Faber     size_t i, j;
707d9e6c9b5SThomas Faber     size_t const limbs = CHARS_TO_LIMBS( buflen );
708c2c66affSColin Finck 
709d9e6c9b5SThomas Faber     /* Ensure that target MPI has exactly the necessary number of limbs */
710d9e6c9b5SThomas Faber     if( X->n != limbs )
711d9e6c9b5SThomas Faber     {
712d9e6c9b5SThomas Faber         mbedtls_mpi_free( X );
713d9e6c9b5SThomas Faber         mbedtls_mpi_init( X );
714d9e6c9b5SThomas Faber         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
715d9e6c9b5SThomas Faber     }
716c2c66affSColin Finck 
717c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
718c2c66affSColin Finck 
719d9e6c9b5SThomas Faber     for( i = buflen, j = 0; i > 0; i--, j++ )
720c2c66affSColin Finck         X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
721c2c66affSColin Finck 
722c2c66affSColin Finck cleanup:
723c2c66affSColin Finck 
724c2c66affSColin Finck     return( ret );
725c2c66affSColin Finck }
726c2c66affSColin Finck 
727c2c66affSColin Finck /*
728c2c66affSColin Finck  * Export X into unsigned binary data, big endian
729c2c66affSColin Finck  */
7300ba5bc40SThomas Faber int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
7310ba5bc40SThomas Faber                               unsigned char *buf, size_t buflen )
732c2c66affSColin Finck {
7330ba5bc40SThomas Faber     size_t stored_bytes = X->n * ciL;
7340ba5bc40SThomas Faber     size_t bytes_to_copy;
7350ba5bc40SThomas Faber     unsigned char *p;
7360ba5bc40SThomas Faber     size_t i;
737c2c66affSColin Finck 
7380ba5bc40SThomas Faber     if( stored_bytes < buflen )
7390ba5bc40SThomas Faber     {
7400ba5bc40SThomas Faber         /* There is enough space in the output buffer. Write initial
7410ba5bc40SThomas Faber          * null bytes and record the position at which to start
7420ba5bc40SThomas Faber          * writing the significant bytes. In this case, the execution
7430ba5bc40SThomas Faber          * trace of this function does not depend on the value of the
7440ba5bc40SThomas Faber          * number. */
7450ba5bc40SThomas Faber         bytes_to_copy = stored_bytes;
7460ba5bc40SThomas Faber         p = buf + buflen - stored_bytes;
7470ba5bc40SThomas Faber         memset( buf, 0, buflen - stored_bytes );
7480ba5bc40SThomas Faber     }
7490ba5bc40SThomas Faber     else
7500ba5bc40SThomas Faber     {
7510ba5bc40SThomas Faber         /* The output buffer is smaller than the allocated size of X.
7520ba5bc40SThomas Faber          * However X may fit if its leading bytes are zero. */
7530ba5bc40SThomas Faber         bytes_to_copy = buflen;
7540ba5bc40SThomas Faber         p = buf;
7550ba5bc40SThomas Faber         for( i = bytes_to_copy; i < stored_bytes; i++ )
7560ba5bc40SThomas Faber         {
7570ba5bc40SThomas Faber             if( GET_BYTE( X, i ) != 0 )
758c2c66affSColin Finck                 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
7590ba5bc40SThomas Faber         }
7600ba5bc40SThomas Faber     }
761c2c66affSColin Finck 
7620ba5bc40SThomas Faber     for( i = 0; i < bytes_to_copy; i++ )
7630ba5bc40SThomas Faber         p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
764c2c66affSColin Finck 
765c2c66affSColin Finck     return( 0 );
766c2c66affSColin Finck }
767c2c66affSColin Finck 
768c2c66affSColin Finck /*
769c2c66affSColin Finck  * Left-shift: X <<= count
770c2c66affSColin Finck  */
771c2c66affSColin Finck int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
772c2c66affSColin Finck {
773c2c66affSColin Finck     int ret;
774c2c66affSColin Finck     size_t i, v0, t1;
775c2c66affSColin Finck     mbedtls_mpi_uint r0 = 0, r1;
776c2c66affSColin Finck 
777c2c66affSColin Finck     v0 = count / (biL    );
778c2c66affSColin Finck     t1 = count & (biL - 1);
779c2c66affSColin Finck 
780c2c66affSColin Finck     i = mbedtls_mpi_bitlen( X ) + count;
781c2c66affSColin Finck 
782c2c66affSColin Finck     if( X->n * biL < i )
783c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
784c2c66affSColin Finck 
785c2c66affSColin Finck     ret = 0;
786c2c66affSColin Finck 
787c2c66affSColin Finck     /*
788c2c66affSColin Finck      * shift by count / limb_size
789c2c66affSColin Finck      */
790c2c66affSColin Finck     if( v0 > 0 )
791c2c66affSColin Finck     {
792c2c66affSColin Finck         for( i = X->n; i > v0; i-- )
793c2c66affSColin Finck             X->p[i - 1] = X->p[i - v0 - 1];
794c2c66affSColin Finck 
795c2c66affSColin Finck         for( ; i > 0; i-- )
796c2c66affSColin Finck             X->p[i - 1] = 0;
797c2c66affSColin Finck     }
798c2c66affSColin Finck 
799c2c66affSColin Finck     /*
800c2c66affSColin Finck      * shift by count % limb_size
801c2c66affSColin Finck      */
802c2c66affSColin Finck     if( t1 > 0 )
803c2c66affSColin Finck     {
804c2c66affSColin Finck         for( i = v0; i < X->n; i++ )
805c2c66affSColin Finck         {
806c2c66affSColin Finck             r1 = X->p[i] >> (biL - t1);
807c2c66affSColin Finck             X->p[i] <<= t1;
808c2c66affSColin Finck             X->p[i] |= r0;
809c2c66affSColin Finck             r0 = r1;
810c2c66affSColin Finck         }
811c2c66affSColin Finck     }
812c2c66affSColin Finck 
813c2c66affSColin Finck cleanup:
814c2c66affSColin Finck 
815c2c66affSColin Finck     return( ret );
816c2c66affSColin Finck }
817c2c66affSColin Finck 
818c2c66affSColin Finck /*
819c2c66affSColin Finck  * Right-shift: X >>= count
820c2c66affSColin Finck  */
821c2c66affSColin Finck int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
822c2c66affSColin Finck {
823c2c66affSColin Finck     size_t i, v0, v1;
824c2c66affSColin Finck     mbedtls_mpi_uint r0 = 0, r1;
825c2c66affSColin Finck 
826c2c66affSColin Finck     v0 = count /  biL;
827c2c66affSColin Finck     v1 = count & (biL - 1);
828c2c66affSColin Finck 
829c2c66affSColin Finck     if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
830c2c66affSColin Finck         return mbedtls_mpi_lset( X, 0 );
831c2c66affSColin Finck 
832c2c66affSColin Finck     /*
833c2c66affSColin Finck      * shift by count / limb_size
834c2c66affSColin Finck      */
835c2c66affSColin Finck     if( v0 > 0 )
836c2c66affSColin Finck     {
837c2c66affSColin Finck         for( i = 0; i < X->n - v0; i++ )
838c2c66affSColin Finck             X->p[i] = X->p[i + v0];
839c2c66affSColin Finck 
840c2c66affSColin Finck         for( ; i < X->n; i++ )
841c2c66affSColin Finck             X->p[i] = 0;
842c2c66affSColin Finck     }
843c2c66affSColin Finck 
844c2c66affSColin Finck     /*
845c2c66affSColin Finck      * shift by count % limb_size
846c2c66affSColin Finck      */
847c2c66affSColin Finck     if( v1 > 0 )
848c2c66affSColin Finck     {
849c2c66affSColin Finck         for( i = X->n; i > 0; i-- )
850c2c66affSColin Finck         {
851c2c66affSColin Finck             r1 = X->p[i - 1] << (biL - v1);
852c2c66affSColin Finck             X->p[i - 1] >>= v1;
853c2c66affSColin Finck             X->p[i - 1] |= r0;
854c2c66affSColin Finck             r0 = r1;
855c2c66affSColin Finck         }
856c2c66affSColin Finck     }
857c2c66affSColin Finck 
858c2c66affSColin Finck     return( 0 );
859c2c66affSColin Finck }
860c2c66affSColin Finck 
861c2c66affSColin Finck /*
862c2c66affSColin Finck  * Compare unsigned values
863c2c66affSColin Finck  */
864c2c66affSColin Finck int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
865c2c66affSColin Finck {
866c2c66affSColin Finck     size_t i, j;
867c2c66affSColin Finck 
868c2c66affSColin Finck     for( i = X->n; i > 0; i-- )
869c2c66affSColin Finck         if( X->p[i - 1] != 0 )
870c2c66affSColin Finck             break;
871c2c66affSColin Finck 
872c2c66affSColin Finck     for( j = Y->n; j > 0; j-- )
873c2c66affSColin Finck         if( Y->p[j - 1] != 0 )
874c2c66affSColin Finck             break;
875c2c66affSColin Finck 
876c2c66affSColin Finck     if( i == 0 && j == 0 )
877c2c66affSColin Finck         return( 0 );
878c2c66affSColin Finck 
879c2c66affSColin Finck     if( i > j ) return(  1 );
880c2c66affSColin Finck     if( j > i ) return( -1 );
881c2c66affSColin Finck 
882c2c66affSColin Finck     for( ; i > 0; i-- )
883c2c66affSColin Finck     {
884c2c66affSColin Finck         if( X->p[i - 1] > Y->p[i - 1] ) return(  1 );
885c2c66affSColin Finck         if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
886c2c66affSColin Finck     }
887c2c66affSColin Finck 
888c2c66affSColin Finck     return( 0 );
889c2c66affSColin Finck }
890c2c66affSColin Finck 
891c2c66affSColin Finck /*
892c2c66affSColin Finck  * Compare signed values
893c2c66affSColin Finck  */
894c2c66affSColin Finck int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
895c2c66affSColin Finck {
896c2c66affSColin Finck     size_t i, j;
897c2c66affSColin Finck 
898c2c66affSColin Finck     for( i = X->n; i > 0; i-- )
899c2c66affSColin Finck         if( X->p[i - 1] != 0 )
900c2c66affSColin Finck             break;
901c2c66affSColin Finck 
902c2c66affSColin Finck     for( j = Y->n; j > 0; j-- )
903c2c66affSColin Finck         if( Y->p[j - 1] != 0 )
904c2c66affSColin Finck             break;
905c2c66affSColin Finck 
906c2c66affSColin Finck     if( i == 0 && j == 0 )
907c2c66affSColin Finck         return( 0 );
908c2c66affSColin Finck 
909c2c66affSColin Finck     if( i > j ) return(  X->s );
910c2c66affSColin Finck     if( j > i ) return( -Y->s );
911c2c66affSColin Finck 
912c2c66affSColin Finck     if( X->s > 0 && Y->s < 0 ) return(  1 );
913c2c66affSColin Finck     if( Y->s > 0 && X->s < 0 ) return( -1 );
914c2c66affSColin Finck 
915c2c66affSColin Finck     for( ; i > 0; i-- )
916c2c66affSColin Finck     {
917c2c66affSColin Finck         if( X->p[i - 1] > Y->p[i - 1] ) return(  X->s );
918c2c66affSColin Finck         if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
919c2c66affSColin Finck     }
920c2c66affSColin Finck 
921c2c66affSColin Finck     return( 0 );
922c2c66affSColin Finck }
923c2c66affSColin Finck 
924*d152519aSThomas Faber /** Decide if an integer is less than the other, without branches.
925*d152519aSThomas Faber  *
926*d152519aSThomas Faber  * \param x         First integer.
927*d152519aSThomas Faber  * \param y         Second integer.
928*d152519aSThomas Faber  *
929*d152519aSThomas Faber  * \return          1 if \p x is less than \p y, 0 otherwise
930*d152519aSThomas Faber  */
931*d152519aSThomas Faber static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
932*d152519aSThomas Faber         const mbedtls_mpi_uint y )
933*d152519aSThomas Faber {
934*d152519aSThomas Faber     mbedtls_mpi_uint ret;
935*d152519aSThomas Faber     mbedtls_mpi_uint cond;
936*d152519aSThomas Faber 
937*d152519aSThomas Faber     /*
938*d152519aSThomas Faber      * Check if the most significant bits (MSB) of the operands are different.
939*d152519aSThomas Faber      */
940*d152519aSThomas Faber     cond = ( x ^ y );
941*d152519aSThomas Faber     /*
942*d152519aSThomas Faber      * If the MSB are the same then the difference x-y will be negative (and
943*d152519aSThomas Faber      * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
944*d152519aSThomas Faber      */
945*d152519aSThomas Faber     ret = ( x - y ) & ~cond;
946*d152519aSThomas Faber     /*
947*d152519aSThomas Faber      * If the MSB are different, then the operand with the MSB of 1 is the
948*d152519aSThomas Faber      * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
949*d152519aSThomas Faber      * the MSB of y is 0.)
950*d152519aSThomas Faber      */
951*d152519aSThomas Faber     ret |= y & cond;
952*d152519aSThomas Faber 
953*d152519aSThomas Faber 
954*d152519aSThomas Faber     ret = ret >> ( biL - 1 );
955*d152519aSThomas Faber 
956*d152519aSThomas Faber     return (unsigned) ret;
957*d152519aSThomas Faber }
958*d152519aSThomas Faber 
959*d152519aSThomas Faber /*
960*d152519aSThomas Faber  * Compare signed values in constant time
961*d152519aSThomas Faber  */
962*d152519aSThomas Faber int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
963*d152519aSThomas Faber         unsigned *ret )
964*d152519aSThomas Faber {
965*d152519aSThomas Faber     size_t i;
966*d152519aSThomas Faber     /* The value of any of these variables is either 0 or 1 at all times. */
967*d152519aSThomas Faber     unsigned cond, done, X_is_negative, Y_is_negative;
968*d152519aSThomas Faber 
969*d152519aSThomas Faber     if( X->n != Y->n )
970*d152519aSThomas Faber         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
971*d152519aSThomas Faber 
972*d152519aSThomas Faber     /*
973*d152519aSThomas Faber      * Set sign_N to 1 if N >= 0, 0 if N < 0.
974*d152519aSThomas Faber      * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
975*d152519aSThomas Faber      */
976*d152519aSThomas Faber     X_is_negative = ( X->s & 2 ) >> 1;
977*d152519aSThomas Faber     Y_is_negative = ( Y->s & 2 ) >> 1;
978*d152519aSThomas Faber 
979*d152519aSThomas Faber     /*
980*d152519aSThomas Faber      * If the signs are different, then the positive operand is the bigger.
981*d152519aSThomas Faber      * That is if X is negative (X_is_negative == 1), then X < Y is true and it
982*d152519aSThomas Faber      * is false if X is positive (X_is_negative == 0).
983*d152519aSThomas Faber      */
984*d152519aSThomas Faber     cond = ( X_is_negative ^ Y_is_negative );
985*d152519aSThomas Faber     *ret = cond & X_is_negative;
986*d152519aSThomas Faber 
987*d152519aSThomas Faber     /*
988*d152519aSThomas Faber      * This is a constant-time function. We might have the result, but we still
989*d152519aSThomas Faber      * need to go through the loop. Record if we have the result already.
990*d152519aSThomas Faber      */
991*d152519aSThomas Faber     done = cond;
992*d152519aSThomas Faber 
993*d152519aSThomas Faber     for( i = X->n; i > 0; i-- )
994*d152519aSThomas Faber     {
995*d152519aSThomas Faber         /*
996*d152519aSThomas Faber          * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
997*d152519aSThomas Faber          * X and Y are negative.
998*d152519aSThomas Faber          *
999*d152519aSThomas Faber          * Again even if we can make a decision, we just mark the result and
1000*d152519aSThomas Faber          * the fact that we are done and continue looping.
1001*d152519aSThomas Faber          */
1002*d152519aSThomas Faber         cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1003*d152519aSThomas Faber         *ret |= cond & ( 1 - done ) & X_is_negative;
1004*d152519aSThomas Faber         done |= cond;
1005*d152519aSThomas Faber 
1006*d152519aSThomas Faber         /*
1007*d152519aSThomas Faber          * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1008*d152519aSThomas Faber          * X and Y are positive.
1009*d152519aSThomas Faber          *
1010*d152519aSThomas Faber          * Again even if we can make a decision, we just mark the result and
1011*d152519aSThomas Faber          * the fact that we are done and continue looping.
1012*d152519aSThomas Faber          */
1013*d152519aSThomas Faber         cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1014*d152519aSThomas Faber         *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
1015*d152519aSThomas Faber         done |= cond;
1016*d152519aSThomas Faber     }
1017*d152519aSThomas Faber 
1018*d152519aSThomas Faber     return( 0 );
1019*d152519aSThomas Faber }
1020*d152519aSThomas Faber 
1021c2c66affSColin Finck /*
1022c2c66affSColin Finck  * Compare signed values
1023c2c66affSColin Finck  */
1024c2c66affSColin Finck int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
1025c2c66affSColin Finck {
1026c2c66affSColin Finck     mbedtls_mpi Y;
1027c2c66affSColin Finck     mbedtls_mpi_uint p[1];
1028c2c66affSColin Finck 
1029c2c66affSColin Finck     *p  = ( z < 0 ) ? -z : z;
1030c2c66affSColin Finck     Y.s = ( z < 0 ) ? -1 : 1;
1031c2c66affSColin Finck     Y.n = 1;
1032c2c66affSColin Finck     Y.p = p;
1033c2c66affSColin Finck 
1034c2c66affSColin Finck     return( mbedtls_mpi_cmp_mpi( X, &Y ) );
1035c2c66affSColin Finck }
1036c2c66affSColin Finck 
1037c2c66affSColin Finck /*
1038c2c66affSColin Finck  * Unsigned addition: X = |A| + |B|  (HAC 14.7)
1039c2c66affSColin Finck  */
1040c2c66affSColin Finck int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1041c2c66affSColin Finck {
1042c2c66affSColin Finck     int ret;
1043c2c66affSColin Finck     size_t i, j;
1044c2c66affSColin Finck     mbedtls_mpi_uint *o, *p, c, tmp;
1045c2c66affSColin Finck 
1046c2c66affSColin Finck     if( X == B )
1047c2c66affSColin Finck     {
1048c2c66affSColin Finck         const mbedtls_mpi *T = A; A = X; B = T;
1049c2c66affSColin Finck     }
1050c2c66affSColin Finck 
1051c2c66affSColin Finck     if( X != A )
1052c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
1053c2c66affSColin Finck 
1054c2c66affSColin Finck     /*
1055c2c66affSColin Finck      * X should always be positive as a result of unsigned additions.
1056c2c66affSColin Finck      */
1057c2c66affSColin Finck     X->s = 1;
1058c2c66affSColin Finck 
1059c2c66affSColin Finck     for( j = B->n; j > 0; j-- )
1060c2c66affSColin Finck         if( B->p[j - 1] != 0 )
1061c2c66affSColin Finck             break;
1062c2c66affSColin Finck 
1063c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1064c2c66affSColin Finck 
1065c2c66affSColin Finck     o = B->p; p = X->p; c = 0;
1066c2c66affSColin Finck 
1067c2c66affSColin Finck     /*
1068c2c66affSColin Finck      * tmp is used because it might happen that p == o
1069c2c66affSColin Finck      */
1070c2c66affSColin Finck     for( i = 0; i < j; i++, o++, p++ )
1071c2c66affSColin Finck     {
1072c2c66affSColin Finck         tmp= *o;
1073c2c66affSColin Finck         *p +=  c; c  = ( *p <  c );
1074c2c66affSColin Finck         *p += tmp; c += ( *p < tmp );
1075c2c66affSColin Finck     }
1076c2c66affSColin Finck 
1077c2c66affSColin Finck     while( c != 0 )
1078c2c66affSColin Finck     {
1079c2c66affSColin Finck         if( i >= X->n )
1080c2c66affSColin Finck         {
1081c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
1082c2c66affSColin Finck             p = X->p + i;
1083c2c66affSColin Finck         }
1084c2c66affSColin Finck 
1085c2c66affSColin Finck         *p += c; c = ( *p < c ); i++; p++;
1086c2c66affSColin Finck     }
1087c2c66affSColin Finck 
1088c2c66affSColin Finck cleanup:
1089c2c66affSColin Finck 
1090c2c66affSColin Finck     return( ret );
1091c2c66affSColin Finck }
1092c2c66affSColin Finck 
1093c2c66affSColin Finck /*
1094c2c66affSColin Finck  * Helper for mbedtls_mpi subtraction
1095c2c66affSColin Finck  */
1096c2c66affSColin Finck static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
1097c2c66affSColin Finck {
1098c2c66affSColin Finck     size_t i;
1099c2c66affSColin Finck     mbedtls_mpi_uint c, z;
1100c2c66affSColin Finck 
1101c2c66affSColin Finck     for( i = c = 0; i < n; i++, s++, d++ )
1102c2c66affSColin Finck     {
1103c2c66affSColin Finck         z = ( *d <  c );     *d -=  c;
1104c2c66affSColin Finck         c = ( *d < *s ) + z; *d -= *s;
1105c2c66affSColin Finck     }
1106c2c66affSColin Finck 
1107c2c66affSColin Finck     while( c != 0 )
1108c2c66affSColin Finck     {
1109c2c66affSColin Finck         z = ( *d < c ); *d -= c;
1110c2c66affSColin Finck         c = z; i++; d++;
1111c2c66affSColin Finck     }
1112c2c66affSColin Finck }
1113c2c66affSColin Finck 
1114c2c66affSColin Finck /*
1115c2c66affSColin Finck  * Unsigned subtraction: X = |A| - |B|  (HAC 14.9)
1116c2c66affSColin Finck  */
1117c2c66affSColin Finck int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1118c2c66affSColin Finck {
1119c2c66affSColin Finck     mbedtls_mpi TB;
1120c2c66affSColin Finck     int ret;
1121c2c66affSColin Finck     size_t n;
1122c2c66affSColin Finck 
1123c2c66affSColin Finck     if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1124c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
1125c2c66affSColin Finck 
1126c2c66affSColin Finck     mbedtls_mpi_init( &TB );
1127c2c66affSColin Finck 
1128c2c66affSColin Finck     if( X == B )
1129c2c66affSColin Finck     {
1130c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
1131c2c66affSColin Finck         B = &TB;
1132c2c66affSColin Finck     }
1133c2c66affSColin Finck 
1134c2c66affSColin Finck     if( X != A )
1135c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
1136c2c66affSColin Finck 
1137c2c66affSColin Finck     /*
1138c2c66affSColin Finck      * X should always be positive as a result of unsigned subtractions.
1139c2c66affSColin Finck      */
1140c2c66affSColin Finck     X->s = 1;
1141c2c66affSColin Finck 
1142c2c66affSColin Finck     ret = 0;
1143c2c66affSColin Finck 
1144c2c66affSColin Finck     for( n = B->n; n > 0; n-- )
1145c2c66affSColin Finck         if( B->p[n - 1] != 0 )
1146c2c66affSColin Finck             break;
1147c2c66affSColin Finck 
1148c2c66affSColin Finck     mpi_sub_hlp( n, B->p, X->p );
1149c2c66affSColin Finck 
1150c2c66affSColin Finck cleanup:
1151c2c66affSColin Finck 
1152c2c66affSColin Finck     mbedtls_mpi_free( &TB );
1153c2c66affSColin Finck 
1154c2c66affSColin Finck     return( ret );
1155c2c66affSColin Finck }
1156c2c66affSColin Finck 
1157c2c66affSColin Finck /*
1158c2c66affSColin Finck  * Signed addition: X = A + B
1159c2c66affSColin Finck  */
1160c2c66affSColin Finck int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1161c2c66affSColin Finck {
1162c2c66affSColin Finck     int ret, s = A->s;
1163c2c66affSColin Finck 
1164c2c66affSColin Finck     if( A->s * B->s < 0 )
1165c2c66affSColin Finck     {
1166c2c66affSColin Finck         if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
1167c2c66affSColin Finck         {
1168c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
1169c2c66affSColin Finck             X->s =  s;
1170c2c66affSColin Finck         }
1171c2c66affSColin Finck         else
1172c2c66affSColin Finck         {
1173c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
1174c2c66affSColin Finck             X->s = -s;
1175c2c66affSColin Finck         }
1176c2c66affSColin Finck     }
1177c2c66affSColin Finck     else
1178c2c66affSColin Finck     {
1179c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
1180c2c66affSColin Finck         X->s = s;
1181c2c66affSColin Finck     }
1182c2c66affSColin Finck 
1183c2c66affSColin Finck cleanup:
1184c2c66affSColin Finck 
1185c2c66affSColin Finck     return( ret );
1186c2c66affSColin Finck }
1187c2c66affSColin Finck 
1188c2c66affSColin Finck /*
1189c2c66affSColin Finck  * Signed subtraction: X = A - B
1190c2c66affSColin Finck  */
1191c2c66affSColin Finck int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1192c2c66affSColin Finck {
1193c2c66affSColin Finck     int ret, s = A->s;
1194c2c66affSColin Finck 
1195c2c66affSColin Finck     if( A->s * B->s > 0 )
1196c2c66affSColin Finck     {
1197c2c66affSColin Finck         if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
1198c2c66affSColin Finck         {
1199c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
1200c2c66affSColin Finck             X->s =  s;
1201c2c66affSColin Finck         }
1202c2c66affSColin Finck         else
1203c2c66affSColin Finck         {
1204c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
1205c2c66affSColin Finck             X->s = -s;
1206c2c66affSColin Finck         }
1207c2c66affSColin Finck     }
1208c2c66affSColin Finck     else
1209c2c66affSColin Finck     {
1210c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
1211c2c66affSColin Finck         X->s = s;
1212c2c66affSColin Finck     }
1213c2c66affSColin Finck 
1214c2c66affSColin Finck cleanup:
1215c2c66affSColin Finck 
1216c2c66affSColin Finck     return( ret );
1217c2c66affSColin Finck }
1218c2c66affSColin Finck 
1219c2c66affSColin Finck /*
1220c2c66affSColin Finck  * Signed addition: X = A + b
1221c2c66affSColin Finck  */
1222c2c66affSColin Finck int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1223c2c66affSColin Finck {
1224c2c66affSColin Finck     mbedtls_mpi _B;
1225c2c66affSColin Finck     mbedtls_mpi_uint p[1];
1226c2c66affSColin Finck 
1227c2c66affSColin Finck     p[0] = ( b < 0 ) ? -b : b;
1228c2c66affSColin Finck     _B.s = ( b < 0 ) ? -1 : 1;
1229c2c66affSColin Finck     _B.n = 1;
1230c2c66affSColin Finck     _B.p = p;
1231c2c66affSColin Finck 
1232c2c66affSColin Finck     return( mbedtls_mpi_add_mpi( X, A, &_B ) );
1233c2c66affSColin Finck }
1234c2c66affSColin Finck 
1235c2c66affSColin Finck /*
1236c2c66affSColin Finck  * Signed subtraction: X = A - b
1237c2c66affSColin Finck  */
1238c2c66affSColin Finck int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1239c2c66affSColin Finck {
1240c2c66affSColin Finck     mbedtls_mpi _B;
1241c2c66affSColin Finck     mbedtls_mpi_uint p[1];
1242c2c66affSColin Finck 
1243c2c66affSColin Finck     p[0] = ( b < 0 ) ? -b : b;
1244c2c66affSColin Finck     _B.s = ( b < 0 ) ? -1 : 1;
1245c2c66affSColin Finck     _B.n = 1;
1246c2c66affSColin Finck     _B.p = p;
1247c2c66affSColin Finck 
1248c2c66affSColin Finck     return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
1249c2c66affSColin Finck }
1250c2c66affSColin Finck 
1251c2c66affSColin Finck /*
1252c2c66affSColin Finck  * Helper for mbedtls_mpi multiplication
1253c2c66affSColin Finck  */
1254c2c66affSColin Finck static
1255c2c66affSColin Finck #if defined(__APPLE__) && defined(__arm__)
1256c2c66affSColin Finck /*
1257c2c66affSColin Finck  * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1258c2c66affSColin Finck  * appears to need this to prevent bad ARM code generation at -O3.
1259c2c66affSColin Finck  */
1260c2c66affSColin Finck __attribute__ ((noinline))
1261c2c66affSColin Finck #endif
1262c2c66affSColin Finck void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b )
1263c2c66affSColin Finck {
1264c2c66affSColin Finck     mbedtls_mpi_uint c = 0, t = 0;
1265c2c66affSColin Finck 
1266c2c66affSColin Finck #if defined(MULADDC_HUIT)
1267c2c66affSColin Finck     for( ; i >= 8; i -= 8 )
1268c2c66affSColin Finck     {
1269c2c66affSColin Finck         MULADDC_INIT
1270c2c66affSColin Finck         MULADDC_HUIT
1271c2c66affSColin Finck         MULADDC_STOP
1272c2c66affSColin Finck     }
1273c2c66affSColin Finck 
1274c2c66affSColin Finck     for( ; i > 0; i-- )
1275c2c66affSColin Finck     {
1276c2c66affSColin Finck         MULADDC_INIT
1277c2c66affSColin Finck         MULADDC_CORE
1278c2c66affSColin Finck         MULADDC_STOP
1279c2c66affSColin Finck     }
1280c2c66affSColin Finck #else /* MULADDC_HUIT */
1281c2c66affSColin Finck     for( ; i >= 16; i -= 16 )
1282c2c66affSColin Finck     {
1283c2c66affSColin Finck         MULADDC_INIT
1284c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1285c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1286c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1287c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1288c2c66affSColin Finck 
1289c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1290c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1291c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1292c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1293c2c66affSColin Finck         MULADDC_STOP
1294c2c66affSColin Finck     }
1295c2c66affSColin Finck 
1296c2c66affSColin Finck     for( ; i >= 8; i -= 8 )
1297c2c66affSColin Finck     {
1298c2c66affSColin Finck         MULADDC_INIT
1299c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1300c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1301c2c66affSColin Finck 
1302c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1303c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1304c2c66affSColin Finck         MULADDC_STOP
1305c2c66affSColin Finck     }
1306c2c66affSColin Finck 
1307c2c66affSColin Finck     for( ; i > 0; i-- )
1308c2c66affSColin Finck     {
1309c2c66affSColin Finck         MULADDC_INIT
1310c2c66affSColin Finck         MULADDC_CORE
1311c2c66affSColin Finck         MULADDC_STOP
1312c2c66affSColin Finck     }
1313c2c66affSColin Finck #endif /* MULADDC_HUIT */
1314c2c66affSColin Finck 
1315c2c66affSColin Finck     t++;
1316c2c66affSColin Finck 
1317c2c66affSColin Finck     do {
1318c2c66affSColin Finck         *d += c; c = ( *d < c ); d++;
1319c2c66affSColin Finck     }
1320c2c66affSColin Finck     while( c != 0 );
1321c2c66affSColin Finck }
1322c2c66affSColin Finck 
1323c2c66affSColin Finck /*
1324c2c66affSColin Finck  * Baseline multiplication: X = A * B  (HAC 14.12)
1325c2c66affSColin Finck  */
1326c2c66affSColin Finck int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1327c2c66affSColin Finck {
1328c2c66affSColin Finck     int ret;
1329c2c66affSColin Finck     size_t i, j;
1330c2c66affSColin Finck     mbedtls_mpi TA, TB;
1331c2c66affSColin Finck 
1332c2c66affSColin Finck     mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
1333c2c66affSColin Finck 
1334c2c66affSColin Finck     if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1335c2c66affSColin Finck     if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
1336c2c66affSColin Finck 
1337c2c66affSColin Finck     for( i = A->n; i > 0; i-- )
1338c2c66affSColin Finck         if( A->p[i - 1] != 0 )
1339c2c66affSColin Finck             break;
1340c2c66affSColin Finck 
1341c2c66affSColin Finck     for( j = B->n; j > 0; j-- )
1342c2c66affSColin Finck         if( B->p[j - 1] != 0 )
1343c2c66affSColin Finck             break;
1344c2c66affSColin Finck 
1345c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1346c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
1347c2c66affSColin Finck 
1348c2c66affSColin Finck     for( i++; j > 0; j-- )
1349c2c66affSColin Finck         mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
1350c2c66affSColin Finck 
1351c2c66affSColin Finck     X->s = A->s * B->s;
1352c2c66affSColin Finck 
1353c2c66affSColin Finck cleanup:
1354c2c66affSColin Finck 
1355c2c66affSColin Finck     mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
1356c2c66affSColin Finck 
1357c2c66affSColin Finck     return( ret );
1358c2c66affSColin Finck }
1359c2c66affSColin Finck 
1360c2c66affSColin Finck /*
1361c2c66affSColin Finck  * Baseline multiplication: X = A * b
1362c2c66affSColin Finck  */
1363c2c66affSColin Finck int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
1364c2c66affSColin Finck {
1365c2c66affSColin Finck     mbedtls_mpi _B;
1366c2c66affSColin Finck     mbedtls_mpi_uint p[1];
1367c2c66affSColin Finck 
1368c2c66affSColin Finck     _B.s = 1;
1369c2c66affSColin Finck     _B.n = 1;
1370c2c66affSColin Finck     _B.p = p;
1371c2c66affSColin Finck     p[0] = b;
1372c2c66affSColin Finck 
1373c2c66affSColin Finck     return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
1374c2c66affSColin Finck }
1375c2c66affSColin Finck 
1376c2c66affSColin Finck /*
1377c2c66affSColin Finck  * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1378c2c66affSColin Finck  * mbedtls_mpi_uint divisor, d
1379c2c66affSColin Finck  */
1380c2c66affSColin Finck static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1381c2c66affSColin Finck             mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
1382c2c66affSColin Finck {
1383c2c66affSColin Finck #if defined(MBEDTLS_HAVE_UDBL)
1384c2c66affSColin Finck     mbedtls_t_udbl dividend, quotient;
1385c2c66affSColin Finck #else
1386c2c66affSColin Finck     const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1387c2c66affSColin Finck     const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
1388c2c66affSColin Finck     mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1389c2c66affSColin Finck     mbedtls_mpi_uint u0_msw, u0_lsw;
1390c2c66affSColin Finck     size_t s;
1391c2c66affSColin Finck #endif
1392c2c66affSColin Finck 
1393c2c66affSColin Finck     /*
1394c2c66affSColin Finck      * Check for overflow
1395c2c66affSColin Finck      */
1396c2c66affSColin Finck     if( 0 == d || u1 >= d )
1397c2c66affSColin Finck     {
1398c2c66affSColin Finck         if (r != NULL) *r = ~0;
1399c2c66affSColin Finck 
1400c2c66affSColin Finck         return ( ~0 );
1401c2c66affSColin Finck     }
1402c2c66affSColin Finck 
1403c2c66affSColin Finck #if defined(MBEDTLS_HAVE_UDBL)
1404c2c66affSColin Finck     dividend  = (mbedtls_t_udbl) u1 << biL;
1405c2c66affSColin Finck     dividend |= (mbedtls_t_udbl) u0;
1406c2c66affSColin Finck     quotient = dividend / d;
1407c2c66affSColin Finck     if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1408c2c66affSColin Finck         quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1409c2c66affSColin Finck 
1410c2c66affSColin Finck     if( r != NULL )
1411c2c66affSColin Finck         *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
1412c2c66affSColin Finck 
1413c2c66affSColin Finck     return (mbedtls_mpi_uint) quotient;
1414c2c66affSColin Finck #else
1415c2c66affSColin Finck 
1416c2c66affSColin Finck     /*
1417c2c66affSColin Finck      * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1418c2c66affSColin Finck      *   Vol. 2 - Seminumerical Algorithms, Knuth
1419c2c66affSColin Finck      */
1420c2c66affSColin Finck 
1421c2c66affSColin Finck     /*
1422c2c66affSColin Finck      * Normalize the divisor, d, and dividend, u0, u1
1423c2c66affSColin Finck      */
1424c2c66affSColin Finck     s = mbedtls_clz( d );
1425c2c66affSColin Finck     d = d << s;
1426c2c66affSColin Finck 
1427c2c66affSColin Finck     u1 = u1 << s;
1428c2c66affSColin Finck     u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
1429c2c66affSColin Finck     u0 =  u0 << s;
1430c2c66affSColin Finck 
1431c2c66affSColin Finck     d1 = d >> biH;
1432c2c66affSColin Finck     d0 = d & uint_halfword_mask;
1433c2c66affSColin Finck 
1434c2c66affSColin Finck     u0_msw = u0 >> biH;
1435c2c66affSColin Finck     u0_lsw = u0 & uint_halfword_mask;
1436c2c66affSColin Finck 
1437c2c66affSColin Finck     /*
1438c2c66affSColin Finck      * Find the first quotient and remainder
1439c2c66affSColin Finck      */
1440c2c66affSColin Finck     q1 = u1 / d1;
1441c2c66affSColin Finck     r0 = u1 - d1 * q1;
1442c2c66affSColin Finck 
1443c2c66affSColin Finck     while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1444c2c66affSColin Finck     {
1445c2c66affSColin Finck         q1 -= 1;
1446c2c66affSColin Finck         r0 += d1;
1447c2c66affSColin Finck 
1448c2c66affSColin Finck         if ( r0 >= radix ) break;
1449c2c66affSColin Finck     }
1450c2c66affSColin Finck 
1451c2c66affSColin Finck     rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
1452c2c66affSColin Finck     q0 = rAX / d1;
1453c2c66affSColin Finck     r0 = rAX - q0 * d1;
1454c2c66affSColin Finck 
1455c2c66affSColin Finck     while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1456c2c66affSColin Finck     {
1457c2c66affSColin Finck         q0 -= 1;
1458c2c66affSColin Finck         r0 += d1;
1459c2c66affSColin Finck 
1460c2c66affSColin Finck         if ( r0 >= radix ) break;
1461c2c66affSColin Finck     }
1462c2c66affSColin Finck 
1463c2c66affSColin Finck     if (r != NULL)
1464c2c66affSColin Finck         *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
1465c2c66affSColin Finck 
1466c2c66affSColin Finck     quotient = q1 * radix + q0;
1467c2c66affSColin Finck 
1468c2c66affSColin Finck     return quotient;
1469c2c66affSColin Finck #endif
1470c2c66affSColin Finck }
1471c2c66affSColin Finck 
1472c2c66affSColin Finck /*
1473c2c66affSColin Finck  * Division by mbedtls_mpi: A = Q * B + R  (HAC 14.20)
1474c2c66affSColin Finck  */
1475c2c66affSColin Finck int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
1476c2c66affSColin Finck {
1477c2c66affSColin Finck     int ret;
1478c2c66affSColin Finck     size_t i, n, t, k;
1479c2c66affSColin Finck     mbedtls_mpi X, Y, Z, T1, T2;
1480c2c66affSColin Finck 
1481c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1482c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
1483c2c66affSColin Finck 
1484c2c66affSColin Finck     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1485c2c66affSColin Finck     mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
1486c2c66affSColin Finck 
1487c2c66affSColin Finck     if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1488c2c66affSColin Finck     {
1489c2c66affSColin Finck         if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1490c2c66affSColin Finck         if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
1491c2c66affSColin Finck         return( 0 );
1492c2c66affSColin Finck     }
1493c2c66affSColin Finck 
1494c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1495c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
1496c2c66affSColin Finck     X.s = Y.s = 1;
1497c2c66affSColin Finck 
1498c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1499c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z,  0 ) );
1500c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1501c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
1502c2c66affSColin Finck 
1503c2c66affSColin Finck     k = mbedtls_mpi_bitlen( &Y ) % biL;
1504c2c66affSColin Finck     if( k < biL - 1 )
1505c2c66affSColin Finck     {
1506c2c66affSColin Finck         k = biL - 1 - k;
1507c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1508c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
1509c2c66affSColin Finck     }
1510c2c66affSColin Finck     else k = 0;
1511c2c66affSColin Finck 
1512c2c66affSColin Finck     n = X.n - 1;
1513c2c66affSColin Finck     t = Y.n - 1;
1514c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
1515c2c66affSColin Finck 
1516c2c66affSColin Finck     while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
1517c2c66affSColin Finck     {
1518c2c66affSColin Finck         Z.p[n - t]++;
1519c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
1520c2c66affSColin Finck     }
1521c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
1522c2c66affSColin Finck 
1523c2c66affSColin Finck     for( i = n; i > t ; i-- )
1524c2c66affSColin Finck     {
1525c2c66affSColin Finck         if( X.p[i] >= Y.p[t] )
1526c2c66affSColin Finck             Z.p[i - t - 1] = ~0;
1527c2c66affSColin Finck         else
1528c2c66affSColin Finck         {
1529c2c66affSColin Finck             Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1530c2c66affSColin Finck                                                             Y.p[t], NULL);
1531c2c66affSColin Finck         }
1532c2c66affSColin Finck 
1533c2c66affSColin Finck         Z.p[i - t - 1]++;
1534c2c66affSColin Finck         do
1535c2c66affSColin Finck         {
1536c2c66affSColin Finck             Z.p[i - t - 1]--;
1537c2c66affSColin Finck 
1538c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
1539c2c66affSColin Finck             T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
1540c2c66affSColin Finck             T1.p[1] = Y.p[t];
1541c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1542c2c66affSColin Finck 
1543c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
1544c2c66affSColin Finck             T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1545c2c66affSColin Finck             T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1546c2c66affSColin Finck             T2.p[2] = X.p[i];
1547c2c66affSColin Finck         }
1548c2c66affSColin Finck         while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
1549c2c66affSColin Finck 
1550c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1551c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1,  biL * ( i - t - 1 ) ) );
1552c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
1553c2c66affSColin Finck 
1554c2c66affSColin Finck         if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
1555c2c66affSColin Finck         {
1556c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1557c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1558c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
1559c2c66affSColin Finck             Z.p[i - t - 1]--;
1560c2c66affSColin Finck         }
1561c2c66affSColin Finck     }
1562c2c66affSColin Finck 
1563c2c66affSColin Finck     if( Q != NULL )
1564c2c66affSColin Finck     {
1565c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
1566c2c66affSColin Finck         Q->s = A->s * B->s;
1567c2c66affSColin Finck     }
1568c2c66affSColin Finck 
1569c2c66affSColin Finck     if( R != NULL )
1570c2c66affSColin Finck     {
1571c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
1572c2c66affSColin Finck         X.s = A->s;
1573c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
1574c2c66affSColin Finck 
1575c2c66affSColin Finck         if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
1576c2c66affSColin Finck             R->s = 1;
1577c2c66affSColin Finck     }
1578c2c66affSColin Finck 
1579c2c66affSColin Finck cleanup:
1580c2c66affSColin Finck 
1581c2c66affSColin Finck     mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1582c2c66affSColin Finck     mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
1583c2c66affSColin Finck 
1584c2c66affSColin Finck     return( ret );
1585c2c66affSColin Finck }
1586c2c66affSColin Finck 
1587c2c66affSColin Finck /*
1588c2c66affSColin Finck  * Division by int: A = Q * b + R
1589c2c66affSColin Finck  */
1590c2c66affSColin Finck int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1591c2c66affSColin Finck {
1592c2c66affSColin Finck     mbedtls_mpi _B;
1593c2c66affSColin Finck     mbedtls_mpi_uint p[1];
1594c2c66affSColin Finck 
1595c2c66affSColin Finck     p[0] = ( b < 0 ) ? -b : b;
1596c2c66affSColin Finck     _B.s = ( b < 0 ) ? -1 : 1;
1597c2c66affSColin Finck     _B.n = 1;
1598c2c66affSColin Finck     _B.p = p;
1599c2c66affSColin Finck 
1600c2c66affSColin Finck     return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
1601c2c66affSColin Finck }
1602c2c66affSColin Finck 
1603c2c66affSColin Finck /*
1604c2c66affSColin Finck  * Modulo: R = A mod B
1605c2c66affSColin Finck  */
1606c2c66affSColin Finck int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
1607c2c66affSColin Finck {
1608c2c66affSColin Finck     int ret;
1609c2c66affSColin Finck 
1610c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1611c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
1612c2c66affSColin Finck 
1613c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
1614c2c66affSColin Finck 
1615c2c66affSColin Finck     while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1616c2c66affSColin Finck       MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
1617c2c66affSColin Finck 
1618c2c66affSColin Finck     while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1619c2c66affSColin Finck       MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
1620c2c66affSColin Finck 
1621c2c66affSColin Finck cleanup:
1622c2c66affSColin Finck 
1623c2c66affSColin Finck     return( ret );
1624c2c66affSColin Finck }
1625c2c66affSColin Finck 
1626c2c66affSColin Finck /*
1627c2c66affSColin Finck  * Modulo: r = A mod b
1628c2c66affSColin Finck  */
1629c2c66affSColin Finck int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1630c2c66affSColin Finck {
1631c2c66affSColin Finck     size_t i;
1632c2c66affSColin Finck     mbedtls_mpi_uint x, y, z;
1633c2c66affSColin Finck 
1634c2c66affSColin Finck     if( b == 0 )
1635c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
1636c2c66affSColin Finck 
1637c2c66affSColin Finck     if( b < 0 )
1638c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
1639c2c66affSColin Finck 
1640c2c66affSColin Finck     /*
1641c2c66affSColin Finck      * handle trivial cases
1642c2c66affSColin Finck      */
1643c2c66affSColin Finck     if( b == 1 )
1644c2c66affSColin Finck     {
1645c2c66affSColin Finck         *r = 0;
1646c2c66affSColin Finck         return( 0 );
1647c2c66affSColin Finck     }
1648c2c66affSColin Finck 
1649c2c66affSColin Finck     if( b == 2 )
1650c2c66affSColin Finck     {
1651c2c66affSColin Finck         *r = A->p[0] & 1;
1652c2c66affSColin Finck         return( 0 );
1653c2c66affSColin Finck     }
1654c2c66affSColin Finck 
1655c2c66affSColin Finck     /*
1656c2c66affSColin Finck      * general case
1657c2c66affSColin Finck      */
1658c2c66affSColin Finck     for( i = A->n, y = 0; i > 0; i-- )
1659c2c66affSColin Finck     {
1660c2c66affSColin Finck         x  = A->p[i - 1];
1661c2c66affSColin Finck         y  = ( y << biH ) | ( x >> biH );
1662c2c66affSColin Finck         z  = y / b;
1663c2c66affSColin Finck         y -= z * b;
1664c2c66affSColin Finck 
1665c2c66affSColin Finck         x <<= biH;
1666c2c66affSColin Finck         y  = ( y << biH ) | ( x >> biH );
1667c2c66affSColin Finck         z  = y / b;
1668c2c66affSColin Finck         y -= z * b;
1669c2c66affSColin Finck     }
1670c2c66affSColin Finck 
1671c2c66affSColin Finck     /*
1672c2c66affSColin Finck      * If A is negative, then the current y represents a negative value.
1673c2c66affSColin Finck      * Flipping it to the positive side.
1674c2c66affSColin Finck      */
1675c2c66affSColin Finck     if( A->s < 0 && y != 0 )
1676c2c66affSColin Finck         y = b - y;
1677c2c66affSColin Finck 
1678c2c66affSColin Finck     *r = y;
1679c2c66affSColin Finck 
1680c2c66affSColin Finck     return( 0 );
1681c2c66affSColin Finck }
1682c2c66affSColin Finck 
1683c2c66affSColin Finck /*
1684c2c66affSColin Finck  * Fast Montgomery initialization (thanks to Tom St Denis)
1685c2c66affSColin Finck  */
1686c2c66affSColin Finck static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
1687c2c66affSColin Finck {
1688c2c66affSColin Finck     mbedtls_mpi_uint x, m0 = N->p[0];
1689c2c66affSColin Finck     unsigned int i;
1690c2c66affSColin Finck 
1691c2c66affSColin Finck     x  = m0;
1692c2c66affSColin Finck     x += ( ( m0 + 2 ) & 4 ) << 1;
1693c2c66affSColin Finck 
1694c2c66affSColin Finck     for( i = biL; i >= 8; i /= 2 )
1695c2c66affSColin Finck         x *= ( 2 - ( m0 * x ) );
1696c2c66affSColin Finck 
1697c2c66affSColin Finck     *mm = ~x + 1;
1698c2c66affSColin Finck }
1699c2c66affSColin Finck 
1700c2c66affSColin Finck /*
1701c2c66affSColin Finck  * Montgomery multiplication: A = A * B * R^-1 mod N  (HAC 14.36)
1702c2c66affSColin Finck  */
1703c2c66affSColin Finck static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1704c2c66affSColin Finck                          const mbedtls_mpi *T )
1705c2c66affSColin Finck {
1706c2c66affSColin Finck     size_t i, n, m;
1707c2c66affSColin Finck     mbedtls_mpi_uint u0, u1, *d;
1708c2c66affSColin Finck 
1709c2c66affSColin Finck     if( T->n < N->n + 1 || T->p == NULL )
1710c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1711c2c66affSColin Finck 
1712c2c66affSColin Finck     memset( T->p, 0, T->n * ciL );
1713c2c66affSColin Finck 
1714c2c66affSColin Finck     d = T->p;
1715c2c66affSColin Finck     n = N->n;
1716c2c66affSColin Finck     m = ( B->n < n ) ? B->n : n;
1717c2c66affSColin Finck 
1718c2c66affSColin Finck     for( i = 0; i < n; i++ )
1719c2c66affSColin Finck     {
1720c2c66affSColin Finck         /*
1721c2c66affSColin Finck          * T = (T + u0*B + u1*N) / 2^biL
1722c2c66affSColin Finck          */
1723c2c66affSColin Finck         u0 = A->p[i];
1724c2c66affSColin Finck         u1 = ( d[0] + u0 * B->p[0] ) * mm;
1725c2c66affSColin Finck 
1726c2c66affSColin Finck         mpi_mul_hlp( m, B->p, d, u0 );
1727c2c66affSColin Finck         mpi_mul_hlp( n, N->p, d, u1 );
1728c2c66affSColin Finck 
1729c2c66affSColin Finck         *d++ = u0; d[n + 1] = 0;
1730c2c66affSColin Finck     }
1731c2c66affSColin Finck 
1732c2c66affSColin Finck     memcpy( A->p, d, ( n + 1 ) * ciL );
1733c2c66affSColin Finck 
1734c2c66affSColin Finck     if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
1735c2c66affSColin Finck         mpi_sub_hlp( n, N->p, A->p );
1736c2c66affSColin Finck     else
1737c2c66affSColin Finck         /* prevent timing attacks */
1738c2c66affSColin Finck         mpi_sub_hlp( n, A->p, T->p );
1739c2c66affSColin Finck 
1740c2c66affSColin Finck     return( 0 );
1741c2c66affSColin Finck }
1742c2c66affSColin Finck 
1743c2c66affSColin Finck /*
1744c2c66affSColin Finck  * Montgomery reduction: A = A * R^-1 mod N
1745c2c66affSColin Finck  */
1746c2c66affSColin Finck static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
1747c2c66affSColin Finck {
1748c2c66affSColin Finck     mbedtls_mpi_uint z = 1;
1749c2c66affSColin Finck     mbedtls_mpi U;
1750c2c66affSColin Finck 
1751c2c66affSColin Finck     U.n = U.s = (int) z;
1752c2c66affSColin Finck     U.p = &z;
1753c2c66affSColin Finck 
1754c2c66affSColin Finck     return( mpi_montmul( A, &U, N, mm, T ) );
1755c2c66affSColin Finck }
1756c2c66affSColin Finck 
1757c2c66affSColin Finck /*
1758c2c66affSColin Finck  * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
1759c2c66affSColin Finck  */
1760c2c66affSColin Finck int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR )
1761c2c66affSColin Finck {
1762c2c66affSColin Finck     int ret;
1763c2c66affSColin Finck     size_t wbits, wsize, one = 1;
1764c2c66affSColin Finck     size_t i, j, nblimbs;
1765c2c66affSColin Finck     size_t bufsize, nbits;
1766c2c66affSColin Finck     mbedtls_mpi_uint ei, mm, state;
1767c2c66affSColin Finck     mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
1768c2c66affSColin Finck     int neg;
1769c2c66affSColin Finck 
1770d9e6c9b5SThomas Faber     if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
1771c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1772c2c66affSColin Finck 
1773c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1774c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1775c2c66affSColin Finck 
1776c2c66affSColin Finck     /*
1777c2c66affSColin Finck      * Init temps and window size
1778c2c66affSColin Finck      */
1779c2c66affSColin Finck     mpi_montg_init( &mm, N );
1780c2c66affSColin Finck     mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1781c2c66affSColin Finck     mbedtls_mpi_init( &Apos );
1782c2c66affSColin Finck     memset( W, 0, sizeof( W ) );
1783c2c66affSColin Finck 
1784c2c66affSColin Finck     i = mbedtls_mpi_bitlen( E );
1785c2c66affSColin Finck 
1786c2c66affSColin Finck     wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1787c2c66affSColin Finck             ( i >  79 ) ? 4 : ( i >  23 ) ? 3 : 1;
1788c2c66affSColin Finck 
1789430656f0SThomas Faber #if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
1790c2c66affSColin Finck     if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1791c2c66affSColin Finck         wsize = MBEDTLS_MPI_WINDOW_SIZE;
1792430656f0SThomas Faber #endif
1793c2c66affSColin Finck 
1794c2c66affSColin Finck     j = N->n + 1;
1795c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1796c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1],  j ) );
1797c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
1798c2c66affSColin Finck 
1799c2c66affSColin Finck     /*
1800c2c66affSColin Finck      * Compensate for negative A (and correct at the end)
1801c2c66affSColin Finck      */
1802c2c66affSColin Finck     neg = ( A->s == -1 );
1803c2c66affSColin Finck     if( neg )
1804c2c66affSColin Finck     {
1805c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
1806c2c66affSColin Finck         Apos.s = 1;
1807c2c66affSColin Finck         A = &Apos;
1808c2c66affSColin Finck     }
1809c2c66affSColin Finck 
1810c2c66affSColin Finck     /*
1811c2c66affSColin Finck      * If 1st call, pre-compute R^2 mod N
1812c2c66affSColin Finck      */
1813c2c66affSColin Finck     if( _RR == NULL || _RR->p == NULL )
1814c2c66affSColin Finck     {
1815c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1816c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1817c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
1818c2c66affSColin Finck 
1819c2c66affSColin Finck         if( _RR != NULL )
1820c2c66affSColin Finck             memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
1821c2c66affSColin Finck     }
1822c2c66affSColin Finck     else
1823c2c66affSColin Finck         memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
1824c2c66affSColin Finck 
1825c2c66affSColin Finck     /*
1826c2c66affSColin Finck      * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1827c2c66affSColin Finck      */
1828c2c66affSColin Finck     if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1829c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
1830c2c66affSColin Finck     else
1831c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
1832c2c66affSColin Finck 
1833c2c66affSColin Finck     MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
1834c2c66affSColin Finck 
1835c2c66affSColin Finck     /*
1836c2c66affSColin Finck      * X = R^2 * R^-1 mod N = R mod N
1837c2c66affSColin Finck      */
1838c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
1839c2c66affSColin Finck     MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
1840c2c66affSColin Finck 
1841c2c66affSColin Finck     if( wsize > 1 )
1842c2c66affSColin Finck     {
1843c2c66affSColin Finck         /*
1844c2c66affSColin Finck          * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1845c2c66affSColin Finck          */
1846c2c66affSColin Finck         j =  one << ( wsize - 1 );
1847c2c66affSColin Finck 
1848c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1849c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1]    ) );
1850c2c66affSColin Finck 
1851c2c66affSColin Finck         for( i = 0; i < wsize - 1; i++ )
1852c2c66affSColin Finck             MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
1853c2c66affSColin Finck 
1854c2c66affSColin Finck         /*
1855c2c66affSColin Finck          * W[i] = W[i - 1] * W[1]
1856c2c66affSColin Finck          */
1857c2c66affSColin Finck         for( i = j + 1; i < ( one << wsize ); i++ )
1858c2c66affSColin Finck         {
1859c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1860c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
1861c2c66affSColin Finck 
1862c2c66affSColin Finck             MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
1863c2c66affSColin Finck         }
1864c2c66affSColin Finck     }
1865c2c66affSColin Finck 
1866c2c66affSColin Finck     nblimbs = E->n;
1867c2c66affSColin Finck     bufsize = 0;
1868c2c66affSColin Finck     nbits   = 0;
1869c2c66affSColin Finck     wbits   = 0;
1870c2c66affSColin Finck     state   = 0;
1871c2c66affSColin Finck 
1872c2c66affSColin Finck     while( 1 )
1873c2c66affSColin Finck     {
1874c2c66affSColin Finck         if( bufsize == 0 )
1875c2c66affSColin Finck         {
1876c2c66affSColin Finck             if( nblimbs == 0 )
1877c2c66affSColin Finck                 break;
1878c2c66affSColin Finck 
1879c2c66affSColin Finck             nblimbs--;
1880c2c66affSColin Finck 
1881c2c66affSColin Finck             bufsize = sizeof( mbedtls_mpi_uint ) << 3;
1882c2c66affSColin Finck         }
1883c2c66affSColin Finck 
1884c2c66affSColin Finck         bufsize--;
1885c2c66affSColin Finck 
1886c2c66affSColin Finck         ei = (E->p[nblimbs] >> bufsize) & 1;
1887c2c66affSColin Finck 
1888c2c66affSColin Finck         /*
1889c2c66affSColin Finck          * skip leading 0s
1890c2c66affSColin Finck          */
1891c2c66affSColin Finck         if( ei == 0 && state == 0 )
1892c2c66affSColin Finck             continue;
1893c2c66affSColin Finck 
1894c2c66affSColin Finck         if( ei == 0 && state == 1 )
1895c2c66affSColin Finck         {
1896c2c66affSColin Finck             /*
1897c2c66affSColin Finck              * out of window, square X
1898c2c66affSColin Finck              */
1899c2c66affSColin Finck             MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
1900c2c66affSColin Finck             continue;
1901c2c66affSColin Finck         }
1902c2c66affSColin Finck 
1903c2c66affSColin Finck         /*
1904c2c66affSColin Finck          * add ei to current window
1905c2c66affSColin Finck          */
1906c2c66affSColin Finck         state = 2;
1907c2c66affSColin Finck 
1908c2c66affSColin Finck         nbits++;
1909c2c66affSColin Finck         wbits |= ( ei << ( wsize - nbits ) );
1910c2c66affSColin Finck 
1911c2c66affSColin Finck         if( nbits == wsize )
1912c2c66affSColin Finck         {
1913c2c66affSColin Finck             /*
1914c2c66affSColin Finck              * X = X^wsize R^-1 mod N
1915c2c66affSColin Finck              */
1916c2c66affSColin Finck             for( i = 0; i < wsize; i++ )
1917c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
1918c2c66affSColin Finck 
1919c2c66affSColin Finck             /*
1920c2c66affSColin Finck              * X = X * W[wbits] R^-1 mod N
1921c2c66affSColin Finck              */
1922c2c66affSColin Finck             MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
1923c2c66affSColin Finck 
1924c2c66affSColin Finck             state--;
1925c2c66affSColin Finck             nbits = 0;
1926c2c66affSColin Finck             wbits = 0;
1927c2c66affSColin Finck         }
1928c2c66affSColin Finck     }
1929c2c66affSColin Finck 
1930c2c66affSColin Finck     /*
1931c2c66affSColin Finck      * process the remaining bits
1932c2c66affSColin Finck      */
1933c2c66affSColin Finck     for( i = 0; i < nbits; i++ )
1934c2c66affSColin Finck     {
1935c2c66affSColin Finck         MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
1936c2c66affSColin Finck 
1937c2c66affSColin Finck         wbits <<= 1;
1938c2c66affSColin Finck 
1939c2c66affSColin Finck         if( ( wbits & ( one << wsize ) ) != 0 )
1940c2c66affSColin Finck             MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
1941c2c66affSColin Finck     }
1942c2c66affSColin Finck 
1943c2c66affSColin Finck     /*
1944c2c66affSColin Finck      * X = A^E * R * R^-1 mod N = A^E mod N
1945c2c66affSColin Finck      */
1946c2c66affSColin Finck     MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
1947c2c66affSColin Finck 
1948c2c66affSColin Finck     if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
1949c2c66affSColin Finck     {
1950c2c66affSColin Finck         X->s = -1;
1951c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
1952c2c66affSColin Finck     }
1953c2c66affSColin Finck 
1954c2c66affSColin Finck cleanup:
1955c2c66affSColin Finck 
1956c2c66affSColin Finck     for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
1957c2c66affSColin Finck         mbedtls_mpi_free( &W[i] );
1958c2c66affSColin Finck 
1959c2c66affSColin Finck     mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
1960c2c66affSColin Finck 
1961c2c66affSColin Finck     if( _RR == NULL || _RR->p == NULL )
1962c2c66affSColin Finck         mbedtls_mpi_free( &RR );
1963c2c66affSColin Finck 
1964c2c66affSColin Finck     return( ret );
1965c2c66affSColin Finck }
1966c2c66affSColin Finck 
1967c2c66affSColin Finck /*
1968c2c66affSColin Finck  * Greatest common divisor: G = gcd(A, B)  (HAC 14.54)
1969c2c66affSColin Finck  */
1970c2c66affSColin Finck int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
1971c2c66affSColin Finck {
1972c2c66affSColin Finck     int ret;
1973c2c66affSColin Finck     size_t lz, lzt;
1974c2c66affSColin Finck     mbedtls_mpi TG, TA, TB;
1975c2c66affSColin Finck 
1976c2c66affSColin Finck     mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
1977c2c66affSColin Finck 
1978c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1979c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
1980c2c66affSColin Finck 
1981c2c66affSColin Finck     lz = mbedtls_mpi_lsb( &TA );
1982c2c66affSColin Finck     lzt = mbedtls_mpi_lsb( &TB );
1983c2c66affSColin Finck 
1984c2c66affSColin Finck     if( lzt < lz )
1985c2c66affSColin Finck         lz = lzt;
1986c2c66affSColin Finck 
1987c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1988c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
1989c2c66affSColin Finck 
1990c2c66affSColin Finck     TA.s = TB.s = 1;
1991c2c66affSColin Finck 
1992c2c66affSColin Finck     while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
1993c2c66affSColin Finck     {
1994c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1995c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
1996c2c66affSColin Finck 
1997c2c66affSColin Finck         if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
1998c2c66affSColin Finck         {
1999c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2000c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
2001c2c66affSColin Finck         }
2002c2c66affSColin Finck         else
2003c2c66affSColin Finck         {
2004c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2005c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
2006c2c66affSColin Finck         }
2007c2c66affSColin Finck     }
2008c2c66affSColin Finck 
2009c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2010c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
2011c2c66affSColin Finck 
2012c2c66affSColin Finck cleanup:
2013c2c66affSColin Finck 
2014c2c66affSColin Finck     mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
2015c2c66affSColin Finck 
2016c2c66affSColin Finck     return( ret );
2017c2c66affSColin Finck }
2018c2c66affSColin Finck 
2019c2c66affSColin Finck /*
2020c2c66affSColin Finck  * Fill X with size bytes of random.
2021c2c66affSColin Finck  *
2022c2c66affSColin Finck  * Use a temporary bytes representation to make sure the result is the same
2023c2c66affSColin Finck  * regardless of the platform endianness (useful when f_rng is actually
2024c2c66affSColin Finck  * deterministic, eg for tests).
2025c2c66affSColin Finck  */
2026c2c66affSColin Finck int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
2027c2c66affSColin Finck                      int (*f_rng)(void *, unsigned char *, size_t),
2028c2c66affSColin Finck                      void *p_rng )
2029c2c66affSColin Finck {
2030c2c66affSColin Finck     int ret;
2031c2c66affSColin Finck     unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
2032c2c66affSColin Finck 
2033c2c66affSColin Finck     if( size > MBEDTLS_MPI_MAX_SIZE )
2034c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2035c2c66affSColin Finck 
2036c2c66affSColin Finck     MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2037c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
2038c2c66affSColin Finck 
2039c2c66affSColin Finck cleanup:
2040d9e6c9b5SThomas Faber     mbedtls_zeroize( buf, sizeof( buf ) );
2041c2c66affSColin Finck     return( ret );
2042c2c66affSColin Finck }
2043c2c66affSColin Finck 
2044c2c66affSColin Finck /*
2045c2c66affSColin Finck  * Modular inverse: X = A^-1 mod N  (HAC 14.61 / 14.64)
2046c2c66affSColin Finck  */
2047c2c66affSColin Finck int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
2048c2c66affSColin Finck {
2049c2c66affSColin Finck     int ret;
2050c2c66affSColin Finck     mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
2051c2c66affSColin Finck 
2052c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
2053c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2054c2c66affSColin Finck 
2055c2c66affSColin Finck     mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2056c2c66affSColin Finck     mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2057c2c66affSColin Finck     mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
2058c2c66affSColin Finck 
2059c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
2060c2c66affSColin Finck 
2061c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
2062c2c66affSColin Finck     {
2063c2c66affSColin Finck         ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2064c2c66affSColin Finck         goto cleanup;
2065c2c66affSColin Finck     }
2066c2c66affSColin Finck 
2067c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2068c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2069c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2070c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
2071c2c66affSColin Finck 
2072c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2073c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2074c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2075c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
2076c2c66affSColin Finck 
2077c2c66affSColin Finck     do
2078c2c66affSColin Finck     {
2079c2c66affSColin Finck         while( ( TU.p[0] & 1 ) == 0 )
2080c2c66affSColin Finck         {
2081c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
2082c2c66affSColin Finck 
2083c2c66affSColin Finck             if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2084c2c66affSColin Finck             {
2085c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2086c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
2087c2c66affSColin Finck             }
2088c2c66affSColin Finck 
2089c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2090c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
2091c2c66affSColin Finck         }
2092c2c66affSColin Finck 
2093c2c66affSColin Finck         while( ( TV.p[0] & 1 ) == 0 )
2094c2c66affSColin Finck         {
2095c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
2096c2c66affSColin Finck 
2097c2c66affSColin Finck             if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2098c2c66affSColin Finck             {
2099c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2100c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
2101c2c66affSColin Finck             }
2102c2c66affSColin Finck 
2103c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2104c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
2105c2c66affSColin Finck         }
2106c2c66affSColin Finck 
2107c2c66affSColin Finck         if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
2108c2c66affSColin Finck         {
2109c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2110c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2111c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
2112c2c66affSColin Finck         }
2113c2c66affSColin Finck         else
2114c2c66affSColin Finck         {
2115c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2116c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2117c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
2118c2c66affSColin Finck         }
2119c2c66affSColin Finck     }
2120c2c66affSColin Finck     while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
2121c2c66affSColin Finck 
2122c2c66affSColin Finck     while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2123c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
2124c2c66affSColin Finck 
2125c2c66affSColin Finck     while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2126c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
2127c2c66affSColin Finck 
2128c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
2129c2c66affSColin Finck 
2130c2c66affSColin Finck cleanup:
2131c2c66affSColin Finck 
2132c2c66affSColin Finck     mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2133c2c66affSColin Finck     mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2134c2c66affSColin Finck     mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
2135c2c66affSColin Finck 
2136c2c66affSColin Finck     return( ret );
2137c2c66affSColin Finck }
2138c2c66affSColin Finck 
2139c2c66affSColin Finck #if defined(MBEDTLS_GENPRIME)
2140c2c66affSColin Finck 
2141c2c66affSColin Finck static const int small_prime[] =
2142c2c66affSColin Finck {
2143c2c66affSColin Finck         3,    5,    7,   11,   13,   17,   19,   23,
2144c2c66affSColin Finck        29,   31,   37,   41,   43,   47,   53,   59,
2145c2c66affSColin Finck        61,   67,   71,   73,   79,   83,   89,   97,
2146c2c66affSColin Finck       101,  103,  107,  109,  113,  127,  131,  137,
2147c2c66affSColin Finck       139,  149,  151,  157,  163,  167,  173,  179,
2148c2c66affSColin Finck       181,  191,  193,  197,  199,  211,  223,  227,
2149c2c66affSColin Finck       229,  233,  239,  241,  251,  257,  263,  269,
2150c2c66affSColin Finck       271,  277,  281,  283,  293,  307,  311,  313,
2151c2c66affSColin Finck       317,  331,  337,  347,  349,  353,  359,  367,
2152c2c66affSColin Finck       373,  379,  383,  389,  397,  401,  409,  419,
2153c2c66affSColin Finck       421,  431,  433,  439,  443,  449,  457,  461,
2154c2c66affSColin Finck       463,  467,  479,  487,  491,  499,  503,  509,
2155c2c66affSColin Finck       521,  523,  541,  547,  557,  563,  569,  571,
2156c2c66affSColin Finck       577,  587,  593,  599,  601,  607,  613,  617,
2157c2c66affSColin Finck       619,  631,  641,  643,  647,  653,  659,  661,
2158c2c66affSColin Finck       673,  677,  683,  691,  701,  709,  719,  727,
2159c2c66affSColin Finck       733,  739,  743,  751,  757,  761,  769,  773,
2160c2c66affSColin Finck       787,  797,  809,  811,  821,  823,  827,  829,
2161c2c66affSColin Finck       839,  853,  857,  859,  863,  877,  881,  883,
2162c2c66affSColin Finck       887,  907,  911,  919,  929,  937,  941,  947,
2163c2c66affSColin Finck       953,  967,  971,  977,  983,  991,  997, -103
2164c2c66affSColin Finck };
2165c2c66affSColin Finck 
2166c2c66affSColin Finck /*
2167c2c66affSColin Finck  * Small divisors test (X must be positive)
2168c2c66affSColin Finck  *
2169c2c66affSColin Finck  * Return values:
2170c2c66affSColin Finck  * 0: no small factor (possible prime, more tests needed)
2171c2c66affSColin Finck  * 1: certain prime
2172c2c66affSColin Finck  * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2173c2c66affSColin Finck  * other negative: error
2174c2c66affSColin Finck  */
2175c2c66affSColin Finck static int mpi_check_small_factors( const mbedtls_mpi *X )
2176c2c66affSColin Finck {
2177c2c66affSColin Finck     int ret = 0;
2178c2c66affSColin Finck     size_t i;
2179c2c66affSColin Finck     mbedtls_mpi_uint r;
2180c2c66affSColin Finck 
2181c2c66affSColin Finck     if( ( X->p[0] & 1 ) == 0 )
2182c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
2183c2c66affSColin Finck 
2184c2c66affSColin Finck     for( i = 0; small_prime[i] > 0; i++ )
2185c2c66affSColin Finck     {
2186c2c66affSColin Finck         if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
2187c2c66affSColin Finck             return( 1 );
2188c2c66affSColin Finck 
2189c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
2190c2c66affSColin Finck 
2191c2c66affSColin Finck         if( r == 0 )
2192c2c66affSColin Finck             return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
2193c2c66affSColin Finck     }
2194c2c66affSColin Finck 
2195c2c66affSColin Finck cleanup:
2196c2c66affSColin Finck     return( ret );
2197c2c66affSColin Finck }
2198c2c66affSColin Finck 
2199c2c66affSColin Finck /*
2200c2c66affSColin Finck  * Miller-Rabin pseudo-primality test  (HAC 4.24)
2201c2c66affSColin Finck  */
22020ba5bc40SThomas Faber static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
2203c2c66affSColin Finck                              int (*f_rng)(void *, unsigned char *, size_t),
2204c2c66affSColin Finck                              void *p_rng )
2205c2c66affSColin Finck {
2206c2c66affSColin Finck     int ret, count;
22070ba5bc40SThomas Faber     size_t i, j, k, s;
2208c2c66affSColin Finck     mbedtls_mpi W, R, T, A, RR;
2209c2c66affSColin Finck 
2210c2c66affSColin Finck     mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2211c2c66affSColin Finck     mbedtls_mpi_init( &RR );
2212c2c66affSColin Finck 
2213c2c66affSColin Finck     /*
2214c2c66affSColin Finck      * W = |X| - 1
2215c2c66affSColin Finck      * R = W >> lsb( W )
2216c2c66affSColin Finck      */
2217c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2218c2c66affSColin Finck     s = mbedtls_mpi_lsb( &W );
2219c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2220c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
2221c2c66affSColin Finck 
2222c2c66affSColin Finck     i = mbedtls_mpi_bitlen( X );
2223c2c66affSColin Finck 
22240ba5bc40SThomas Faber     for( i = 0; i < rounds; i++ )
2225c2c66affSColin Finck     {
2226c2c66affSColin Finck         /*
2227c2c66affSColin Finck          * pick a random A, 1 < A < |X| - 1
2228c2c66affSColin Finck          */
2229c2c66affSColin Finck         count = 0;
2230c2c66affSColin Finck         do {
2231c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
2232c2c66affSColin Finck 
2233c2c66affSColin Finck             j = mbedtls_mpi_bitlen( &A );
2234c2c66affSColin Finck             k = mbedtls_mpi_bitlen( &W );
2235c2c66affSColin Finck             if (j > k) {
22360ba5bc40SThomas Faber                 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
2237c2c66affSColin Finck             }
2238c2c66affSColin Finck 
2239c2c66affSColin Finck             if (count++ > 30) {
2240c1eccaffSThomas Faber                 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2241c1eccaffSThomas Faber                 goto cleanup;
2242c2c66affSColin Finck             }
2243c2c66affSColin Finck 
2244c2c66affSColin Finck         } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2245c2c66affSColin Finck                   mbedtls_mpi_cmp_int( &A, 1 )  <= 0    );
2246c2c66affSColin Finck 
2247c2c66affSColin Finck         /*
2248c2c66affSColin Finck          * A = A^R mod |X|
2249c2c66affSColin Finck          */
2250c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
2251c2c66affSColin Finck 
2252c2c66affSColin Finck         if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2253c2c66affSColin Finck             mbedtls_mpi_cmp_int( &A,  1 ) == 0 )
2254c2c66affSColin Finck             continue;
2255c2c66affSColin Finck 
2256c2c66affSColin Finck         j = 1;
2257c2c66affSColin Finck         while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
2258c2c66affSColin Finck         {
2259c2c66affSColin Finck             /*
2260c2c66affSColin Finck              * A = A * A mod |X|
2261c2c66affSColin Finck              */
2262c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2263c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X  ) );
2264c2c66affSColin Finck 
2265c2c66affSColin Finck             if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
2266c2c66affSColin Finck                 break;
2267c2c66affSColin Finck 
2268c2c66affSColin Finck             j++;
2269c2c66affSColin Finck         }
2270c2c66affSColin Finck 
2271c2c66affSColin Finck         /*
2272c2c66affSColin Finck          * not prime if A != |X| - 1 or A == 1
2273c2c66affSColin Finck          */
2274c2c66affSColin Finck         if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2275c2c66affSColin Finck             mbedtls_mpi_cmp_int( &A,  1 ) == 0 )
2276c2c66affSColin Finck         {
2277c2c66affSColin Finck             ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2278c2c66affSColin Finck             break;
2279c2c66affSColin Finck         }
2280c2c66affSColin Finck     }
2281c2c66affSColin Finck 
2282c2c66affSColin Finck cleanup:
2283c2c66affSColin Finck     mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2284c2c66affSColin Finck     mbedtls_mpi_free( &RR );
2285c2c66affSColin Finck 
2286c2c66affSColin Finck     return( ret );
2287c2c66affSColin Finck }
2288c2c66affSColin Finck 
2289c2c66affSColin Finck /*
2290c2c66affSColin Finck  * Pseudo-primality test: small factors, then Miller-Rabin
2291c2c66affSColin Finck  */
22920ba5bc40SThomas Faber static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
2293c2c66affSColin Finck                   int (*f_rng)(void *, unsigned char *, size_t),
2294c2c66affSColin Finck                   void *p_rng )
2295c2c66affSColin Finck {
2296c2c66affSColin Finck     int ret;
2297c2c66affSColin Finck     mbedtls_mpi XX;
2298c2c66affSColin Finck 
2299c2c66affSColin Finck     XX.s = 1;
2300c2c66affSColin Finck     XX.n = X->n;
2301c2c66affSColin Finck     XX.p = X->p;
2302c2c66affSColin Finck 
2303c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2304c2c66affSColin Finck         mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2305c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
2306c2c66affSColin Finck 
2307c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
2308c2c66affSColin Finck         return( 0 );
2309c2c66affSColin Finck 
2310c2c66affSColin Finck     if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2311c2c66affSColin Finck     {
2312c2c66affSColin Finck         if( ret == 1 )
2313c2c66affSColin Finck             return( 0 );
2314c2c66affSColin Finck 
2315c2c66affSColin Finck         return( ret );
2316c2c66affSColin Finck     }
2317c2c66affSColin Finck 
23180ba5bc40SThomas Faber     return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
23190ba5bc40SThomas Faber }
23200ba5bc40SThomas Faber 
23210ba5bc40SThomas Faber /*
23220ba5bc40SThomas Faber  * Pseudo-primality test, error probability 2^-80
23230ba5bc40SThomas Faber  */
23240ba5bc40SThomas Faber int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
23250ba5bc40SThomas Faber                   int (*f_rng)(void *, unsigned char *, size_t),
23260ba5bc40SThomas Faber                   void *p_rng )
23270ba5bc40SThomas Faber {
23280ba5bc40SThomas Faber     return mpi_is_prime_internal( X, 40, f_rng, p_rng );
2329c2c66affSColin Finck }
2330c2c66affSColin Finck 
2331c2c66affSColin Finck /*
2332c2c66affSColin Finck  * Prime number generation
2333c2c66affSColin Finck  */
2334c2c66affSColin Finck int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
2335c2c66affSColin Finck                    int (*f_rng)(void *, unsigned char *, size_t),
2336c2c66affSColin Finck                    void *p_rng )
2337c2c66affSColin Finck {
2338c2c66affSColin Finck     int ret;
2339c2c66affSColin Finck     size_t k, n;
23400ba5bc40SThomas Faber     int rounds;
2341c2c66affSColin Finck     mbedtls_mpi_uint r;
2342c2c66affSColin Finck     mbedtls_mpi Y;
2343c2c66affSColin Finck 
2344c2c66affSColin Finck     if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2345c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2346c2c66affSColin Finck 
2347c2c66affSColin Finck     mbedtls_mpi_init( &Y );
2348c2c66affSColin Finck 
2349c2c66affSColin Finck     n = BITS_TO_LIMBS( nbits );
2350c2c66affSColin Finck 
23510ba5bc40SThomas Faber     /*
23520ba5bc40SThomas Faber      * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
23530ba5bc40SThomas Faber      */
23540ba5bc40SThomas Faber     rounds = ( ( nbits >= 1300 ) ?  2 : ( nbits >=  850 ) ?  3 :
23550ba5bc40SThomas Faber                ( nbits >=  650 ) ?  4 : ( nbits >=  350 ) ?  8 :
23560ba5bc40SThomas Faber                ( nbits >=  250 ) ? 12 : ( nbits >=  150 ) ? 18 : 27 );
23570ba5bc40SThomas Faber 
2358c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2359c2c66affSColin Finck 
2360c2c66affSColin Finck     k = mbedtls_mpi_bitlen( X );
2361c2c66affSColin Finck     if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
2362c2c66affSColin Finck 
2363c2c66affSColin Finck     mbedtls_mpi_set_bit( X, nbits-1, 1 );
2364c2c66affSColin Finck 
2365c2c66affSColin Finck     X->p[0] |= 1;
2366c2c66affSColin Finck 
2367c2c66affSColin Finck     if( dh_flag == 0 )
2368c2c66affSColin Finck     {
23690ba5bc40SThomas Faber         while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
2370c2c66affSColin Finck         {
2371c2c66affSColin Finck             if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2372c2c66affSColin Finck                 goto cleanup;
2373c2c66affSColin Finck 
2374c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
2375c2c66affSColin Finck         }
2376c2c66affSColin Finck     }
2377c2c66affSColin Finck     else
2378c2c66affSColin Finck     {
2379c2c66affSColin Finck         /*
2380c2c66affSColin Finck          * An necessary condition for Y and X = 2Y + 1 to be prime
2381c2c66affSColin Finck          * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2382c2c66affSColin Finck          * Make sure it is satisfied, while keeping X = 3 mod 4
2383c2c66affSColin Finck          */
2384c2c66affSColin Finck 
2385c2c66affSColin Finck         X->p[0] |= 2;
2386c2c66affSColin Finck 
2387c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2388c2c66affSColin Finck         if( r == 0 )
2389c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2390c2c66affSColin Finck         else if( r == 1 )
2391c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2392c2c66affSColin Finck 
2393c2c66affSColin Finck         /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2394c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2395c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2396c2c66affSColin Finck 
2397c2c66affSColin Finck         while( 1 )
2398c2c66affSColin Finck         {
2399c2c66affSColin Finck             /*
2400c2c66affSColin Finck              * First, check small factors for X and Y
2401c2c66affSColin Finck              * before doing Miller-Rabin on any of them
2402c2c66affSColin Finck              */
2403c2c66affSColin Finck             if( ( ret = mpi_check_small_factors(  X         ) ) == 0 &&
2404c2c66affSColin Finck                 ( ret = mpi_check_small_factors( &Y         ) ) == 0 &&
24050ba5bc40SThomas Faber                 ( ret = mpi_miller_rabin(  X, rounds, f_rng, p_rng  ) )
24060ba5bc40SThomas Faber                                                                 == 0 &&
24070ba5bc40SThomas Faber                 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng  ) )
24080ba5bc40SThomas Faber                                                                 == 0 )
2409c2c66affSColin Finck             {
2410c2c66affSColin Finck                 break;
2411c2c66affSColin Finck             }
2412c2c66affSColin Finck 
2413c2c66affSColin Finck             if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2414c2c66affSColin Finck                 goto cleanup;
2415c2c66affSColin Finck 
2416c2c66affSColin Finck             /*
2417c2c66affSColin Finck              * Next candidates. We want to preserve Y = (X-1) / 2 and
2418c2c66affSColin Finck              * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2419c2c66affSColin Finck              * so up Y by 6 and X by 12.
2420c2c66affSColin Finck              */
2421c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(  X,  X, 12 ) );
2422c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6  ) );
2423c2c66affSColin Finck         }
2424c2c66affSColin Finck     }
2425c2c66affSColin Finck 
2426c2c66affSColin Finck cleanup:
2427c2c66affSColin Finck 
2428c2c66affSColin Finck     mbedtls_mpi_free( &Y );
2429c2c66affSColin Finck 
2430c2c66affSColin Finck     return( ret );
2431c2c66affSColin Finck }
2432c2c66affSColin Finck 
2433c2c66affSColin Finck #endif /* MBEDTLS_GENPRIME */
2434c2c66affSColin Finck 
2435c2c66affSColin Finck #if defined(MBEDTLS_SELF_TEST)
2436c2c66affSColin Finck 
2437c2c66affSColin Finck #define GCD_PAIR_COUNT  3
2438c2c66affSColin Finck 
2439c2c66affSColin Finck static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2440c2c66affSColin Finck {
2441c2c66affSColin Finck     { 693, 609, 21 },
2442c2c66affSColin Finck     { 1764, 868, 28 },
2443c2c66affSColin Finck     { 768454923, 542167814, 1 }
2444c2c66affSColin Finck };
2445c2c66affSColin Finck 
2446c2c66affSColin Finck /*
2447c2c66affSColin Finck  * Checkup routine
2448c2c66affSColin Finck  */
2449c2c66affSColin Finck int mbedtls_mpi_self_test( int verbose )
2450c2c66affSColin Finck {
2451c2c66affSColin Finck     int ret, i;
2452c2c66affSColin Finck     mbedtls_mpi A, E, N, X, Y, U, V;
2453c2c66affSColin Finck 
2454c2c66affSColin Finck     mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2455c2c66affSColin Finck     mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
2456c2c66affSColin Finck 
2457c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
2458c2c66affSColin Finck         "EFE021C2645FD1DC586E69184AF4A31E" \
2459c2c66affSColin Finck         "D5F53E93B5F123FA41680867BA110131" \
2460c2c66affSColin Finck         "944FE7952E2517337780CB0DB80E61AA" \
2461c2c66affSColin Finck         "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2462c2c66affSColin Finck 
2463c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
2464c2c66affSColin Finck         "B2E7EFD37075B9F03FF989C7C5051C20" \
2465c2c66affSColin Finck         "34D2A323810251127E7BF8625A4F49A5" \
2466c2c66affSColin Finck         "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2467c2c66affSColin Finck         "5B5C25763222FEFCCFC38B832366C29E" ) );
2468c2c66affSColin Finck 
2469c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
2470c2c66affSColin Finck         "0066A198186C18C10B2F5ED9B522752A" \
2471c2c66affSColin Finck         "9830B69916E535C8F047518A889A43A5" \
2472c2c66affSColin Finck         "94B6BED27A168D31D4A52F88925AA8F5" ) );
2473c2c66affSColin Finck 
2474c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
2475c2c66affSColin Finck 
2476c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
2477c2c66affSColin Finck         "602AB7ECA597A3D6B56FF9829A5E8B85" \
2478c2c66affSColin Finck         "9E857EA95A03512E2BAE7391688D264A" \
2479c2c66affSColin Finck         "A5663B0341DB9CCFD2C4C5F421FEC814" \
2480c2c66affSColin Finck         "8001B72E848A38CAE1C65F78E56ABDEF" \
2481c2c66affSColin Finck         "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2482c2c66affSColin Finck         "ECF677152EF804370C1A305CAF3B5BF1" \
2483c2c66affSColin Finck         "30879B56C61DE584A0F53A2447A51E" ) );
2484c2c66affSColin Finck 
2485c2c66affSColin Finck     if( verbose != 0 )
2486c2c66affSColin Finck         mbedtls_printf( "  MPI test #1 (mul_mpi): " );
2487c2c66affSColin Finck 
2488c2c66affSColin Finck     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
2489c2c66affSColin Finck     {
2490c2c66affSColin Finck         if( verbose != 0 )
2491c2c66affSColin Finck             mbedtls_printf( "failed\n" );
2492c2c66affSColin Finck 
2493c2c66affSColin Finck         ret = 1;
2494c2c66affSColin Finck         goto cleanup;
2495c2c66affSColin Finck     }
2496c2c66affSColin Finck 
2497c2c66affSColin Finck     if( verbose != 0 )
2498c2c66affSColin Finck         mbedtls_printf( "passed\n" );
2499c2c66affSColin Finck 
2500c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
2501c2c66affSColin Finck 
2502c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
2503c2c66affSColin Finck         "256567336059E52CAE22925474705F39A94" ) );
2504c2c66affSColin Finck 
2505c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
2506c2c66affSColin Finck         "6613F26162223DF488E9CD48CC132C7A" \
2507c2c66affSColin Finck         "0AC93C701B001B092E4E5B9F73BCD27B" \
2508c2c66affSColin Finck         "9EE50D0657C77F374E903CDFA4C642" ) );
2509c2c66affSColin Finck 
2510c2c66affSColin Finck     if( verbose != 0 )
2511c2c66affSColin Finck         mbedtls_printf( "  MPI test #2 (div_mpi): " );
2512c2c66affSColin Finck 
2513c2c66affSColin Finck     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2514c2c66affSColin Finck         mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
2515c2c66affSColin Finck     {
2516c2c66affSColin Finck         if( verbose != 0 )
2517c2c66affSColin Finck             mbedtls_printf( "failed\n" );
2518c2c66affSColin Finck 
2519c2c66affSColin Finck         ret = 1;
2520c2c66affSColin Finck         goto cleanup;
2521c2c66affSColin Finck     }
2522c2c66affSColin Finck 
2523c2c66affSColin Finck     if( verbose != 0 )
2524c2c66affSColin Finck         mbedtls_printf( "passed\n" );
2525c2c66affSColin Finck 
2526c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2527c2c66affSColin Finck 
2528c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
2529c2c66affSColin Finck         "36E139AEA55215609D2816998ED020BB" \
2530c2c66affSColin Finck         "BD96C37890F65171D948E9BC7CBAA4D9" \
2531c2c66affSColin Finck         "325D24D6A3C12710F10A09FA08AB87" ) );
2532c2c66affSColin Finck 
2533c2c66affSColin Finck     if( verbose != 0 )
2534c2c66affSColin Finck         mbedtls_printf( "  MPI test #3 (exp_mod): " );
2535c2c66affSColin Finck 
2536c2c66affSColin Finck     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
2537c2c66affSColin Finck     {
2538c2c66affSColin Finck         if( verbose != 0 )
2539c2c66affSColin Finck             mbedtls_printf( "failed\n" );
2540c2c66affSColin Finck 
2541c2c66affSColin Finck         ret = 1;
2542c2c66affSColin Finck         goto cleanup;
2543c2c66affSColin Finck     }
2544c2c66affSColin Finck 
2545c2c66affSColin Finck     if( verbose != 0 )
2546c2c66affSColin Finck         mbedtls_printf( "passed\n" );
2547c2c66affSColin Finck 
2548c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
2549c2c66affSColin Finck 
2550c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
2551c2c66affSColin Finck         "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2552c2c66affSColin Finck         "C3DBA76456363A10869622EAC2DD84EC" \
2553c2c66affSColin Finck         "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2554c2c66affSColin Finck 
2555c2c66affSColin Finck     if( verbose != 0 )
2556c2c66affSColin Finck         mbedtls_printf( "  MPI test #4 (inv_mod): " );
2557c2c66affSColin Finck 
2558c2c66affSColin Finck     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
2559c2c66affSColin Finck     {
2560c2c66affSColin Finck         if( verbose != 0 )
2561c2c66affSColin Finck             mbedtls_printf( "failed\n" );
2562c2c66affSColin Finck 
2563c2c66affSColin Finck         ret = 1;
2564c2c66affSColin Finck         goto cleanup;
2565c2c66affSColin Finck     }
2566c2c66affSColin Finck 
2567c2c66affSColin Finck     if( verbose != 0 )
2568c2c66affSColin Finck         mbedtls_printf( "passed\n" );
2569c2c66affSColin Finck 
2570c2c66affSColin Finck     if( verbose != 0 )
2571c2c66affSColin Finck         mbedtls_printf( "  MPI test #5 (simple gcd): " );
2572c2c66affSColin Finck 
2573c2c66affSColin Finck     for( i = 0; i < GCD_PAIR_COUNT; i++ )
2574c2c66affSColin Finck     {
2575c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2576c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
2577c2c66affSColin Finck 
2578c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
2579c2c66affSColin Finck 
2580c2c66affSColin Finck         if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2581c2c66affSColin Finck         {
2582c2c66affSColin Finck             if( verbose != 0 )
2583c2c66affSColin Finck                 mbedtls_printf( "failed at %d\n", i );
2584c2c66affSColin Finck 
2585c2c66affSColin Finck             ret = 1;
2586c2c66affSColin Finck             goto cleanup;
2587c2c66affSColin Finck         }
2588c2c66affSColin Finck     }
2589c2c66affSColin Finck 
2590c2c66affSColin Finck     if( verbose != 0 )
2591c2c66affSColin Finck         mbedtls_printf( "passed\n" );
2592c2c66affSColin Finck 
2593c2c66affSColin Finck cleanup:
2594c2c66affSColin Finck 
2595c2c66affSColin Finck     if( ret != 0 && verbose != 0 )
2596c2c66affSColin Finck         mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
2597c2c66affSColin Finck 
2598c2c66affSColin Finck     mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2599c2c66affSColin Finck     mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
2600c2c66affSColin Finck 
2601c2c66affSColin Finck     if( verbose != 0 )
2602c2c66affSColin Finck         mbedtls_printf( "\n" );
2603c2c66affSColin Finck 
2604c2c66affSColin Finck     return( ret );
2605c2c66affSColin Finck }
2606c2c66affSColin Finck 
2607c2c66affSColin Finck #endif /* MBEDTLS_SELF_TEST */
2608c2c66affSColin Finck 
2609c2c66affSColin Finck #endif /* MBEDTLS_BIGNUM_C */
2610